大疆员工爆料:项目组为了赶进度,天天加班,一年的项目,几个月就赶出来了。结果,项目刚交付,他们就被释放了。

文摘   2024-11-16 11:00   陕西  
今天又有一个让人忍不住吐槽的热点!来自大疆的员工爆料,隔壁项目组为了赶进度,拼命加班,结果原本一年的项目硬生生被压缩成几个月就做出来了。但好戏还在后头——项目刚交付完,他们就被“释放”了。
说实话,作为程序员,看到这样的新闻,我内心真的是五味杂陈。
一方面,大家都知道,技术行业加班是家常便饭,尤其是面对紧迫的上线节点。可另一方面,这种“赶工模式”简直是自掘坟墓。项目交付了,员工也跟着“交付”了,那到底是为了什么呢?🤔

所以,大家工作一定要理智,拼命加班未必是好事。做得好,能走得远;做得快,能不能走得稳,就得看老板和团队的眼光了。

算法题:数字 1 的个数

今天我们来聊一个看似简单,但其实挺有意思的编程题目:数字 1 的个数
题目大致的意思是这样的:给定一个整数 n,你需要统计从 1n 的数字中,数字 1 出现的次数。这里的数字 1 不单指整数中的“1”,而是指所有从 1 到 n 这个范围内,出现的每个数字 1。
首先,我们从暴力解法开始:

简单暴力解法

最直接的办法就是,遍历从 1 到 n 的所有数字,将它们转换成字符串,然后检查每个数字中有多少个“1”。比如:
public class CountOnes {
    public static int countDigitOne(int n) {
        int count = 0;
        for (int i = 1; i <= n; i++) {
            String numStr = String.valueOf(i);
            for (char c : numStr.toCharArray()) {
                if (c == '1') {
                    count++;
                }
            }
        }
        return count;
    }

    public static void main(String[] args) {
        int n = 13;
        System.out.println("1的个数是: " + countDigitOne(n));
    }
}
这个方法简单明了:对于每个数字,把它转换成字符串,然后逐个字符检查是否为 '1'。可是,这种做法的时间复杂度是 O(n * k),其中 k 是每个数字的长度。这种方法在 n 很大时效率就会下降,特别是在 n 接近 10^9 的时候,性能问题就显得尤为严重了。

高效算法:数学分析

既然暴力解法那么慢,我们来试试更高效的办法。我们可以从数字的结构入手,利用数学方法来优化。
我们可以分析一下数字的结构。比如,在数字 1 到 100 之间,1 会出现在哪些位置呢?我们可以将每个数字视为一个“位”,而且从高位到低位逐位考虑数字 1 的出现次数。
以数字 13 为例,假设我们有一个数字 x = 13,我们可以把它分解为以下几部分:
  • 百位(高位):0 或 1
  • 十位:0-9
  • 个位:0-9
我们要统计在从 1 到 13 中,每个位上出现 1 的次数。我们可以根据各个位的值来判断 1 出现的次数。

更高效的解法

通过这种方式,我们可以减少大量不必要的计算,直接通过数学推导来解决问题。具体的做法是,通过每一位的数字来分配“1”出现的次数。假设我们要计算一个位置上的 1 的出现次数,可以利用如下的公式:
public class CountOnes {
    public static int countDigitOne(int n) {
        int count = 0;
        for (long factor = 1; factor <= n; factor *= 10) {
            long lowerNumbers = n - (n / factor) * factor;
            long currentDigit = (n / factor) % 10;
            long higherNumbers = n / (factor * 10);
            
            if (currentDigit == 0) {
                count += higherNumbers * factor;
            } else if (currentDigit == 1) {
                count += higherNumbers * factor + lowerNumbers + 1;
            } else {
                count += (higherNumbers + 1) * factor;
            }
        }
        return count;
    }

    public static void main(String[] args) {
        int n = 13;
        System.out.println("1的个数是: " + countDigitOne(n)); // 输出结果应该是 6
    }
}
这段代码中,我们从低位到高位逐位分析。每次计算时,我们根据当前位的数字判断前面和后面数字的情况,从而推算出当前位上数字 1 出现的次数。

代码解析

  1. 循环每一位:通过 factor(即 10 的幂次方)逐位检查数字。比如,从个位开始,再到十位、百位,以此类推。
  2. 三部分拆解:对于每一位,我们将数字拆解为三部分:低位数字(lowerNumbers)、当前位数字(currentDigit)和高位数字(higherNumbers)。然后根据 currentDigit 的值来判断 1 在当前位上出现的次数。
  • 如果当前位数字是 0,那么当前位上不会有 1,次数等于高位部分的次数乘以当前位的因子。
  • 如果当前位数字是 1,那么当前位上会有额外的 1,次数等于高位部分的次数乘以当前位的因子再加上低位数字加一。
  • 如果当前位数字大于 1,说明当前位上肯定有 1,次数等于高位部分的次数加一,再乘以当前位的因子。

性能分析

这个方法的时间复杂度是 O(log n),其中 log n 是数字的位数。比暴力解法 O(n * k) 要高效得多,尤其是在 n 很大的情况下,能够显著提高性能。
希望这个方法能帮到你!如果有任何问题,或者你有更好的解法,欢迎留言一起讨论。代码的效率永远是程序员们追求的目标嘛💻。

-END-


ok,今天先说到这,老规矩,给大家分享一份不错的副业资料,感兴趣的同学找我领取。

以上,就是今天的分享了,看完文章记得右下角给何老师点赞,也欢迎在评论区写下你的留言

程序员老鬼
10年+老程序员,专注于AI知识普及,已打造多门AI课程,本号主要分享国内AI工具、AI绘画提示词、Chat教程、AI换脸、Chat中文指令、Sora教程等,帮助读者解决AI工具使用疑难问题。
 最新文章