mirror of
https://github.com/chefyuan/algorithm-base.git
synced 2025-08-02 14:01:34 +00:00
代码重构 【Github Actions】
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# 我太喜欢这个题了
|
||||
|
||||
> 如果阅读时,发现错误,或者动画不可以显示的问题可以添加我微信好友 **[tan45du_one](https://raw.githubusercontent.com/tan45du/tan45du.github.io/master/个人微信.15egrcgqd94w.jpg)** ,备注 github + 题目 + 问题 向我反馈
|
||||
> 如果阅读时,发现错误,或者动画不可以显示的问题可以添加我微信好友 **[tan45du_one](https://raw.githubusercontent.com/tan45du/tan45du.github.io/master/个人微信.15egrcgqd94w.jpg)** ,备注 github + 题目 + 问题 向我反馈
|
||||
>
|
||||
> 感谢支持,该仓库会一直维护,希望对各位有一丢丢帮助。
|
||||
>
|
||||
@@ -44,19 +44,15 @@
|
||||
|
||||
我们假设 n = abcd,某个四位数。
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
那我们完全可以统计每一位上 1 出现的次数,个数上 1 出现的次数,十位上 1 出现的次数,百位 ,千位。。。
|
||||
|
||||
也就是说**小于等于 n 的所有数字中**,个位上出现 1 的次数 + 十位出现 1 的次数 + 。。。最后得到的就是总的出现次数。
|
||||
|
||||
见下图
|
||||
|
||||
我们假设 n = 13 (用个小点的数,比较容易举例)
|
||||
我们假设 n = 13 (用个小点的数,比较容易举例)
|
||||
|
||||

|
||||
|
||||
@@ -69,18 +65,13 @@
|
||||
> 另外我们发现 11 这个数,会被统计 2 次,它的十位和个位都为 1 ,
|
||||
>
|
||||
> 而我们这个题目是要统计 1 出现的次数,而不是统计包含 1 的整数,所以上诉方法不会出现重复统计的情况。
|
||||
>
|
||||
|
||||
我们题目已经有大概思路啦,下面的难点就是如何统计每一位中 1 出现的次数呢?
|
||||
|
||||
我们完全可以通过遍历 n 的每一位来得到总个数,见下图
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
假设我们想要得到十位上 1 出现的次数,当前我们指针指向十位,
|
||||
|
||||
我们称之为当前位。num 则代表当前位的位因子,当前位为个位时 num = 1,十位时为 10,百位时为 100....
|
||||
@@ -95,7 +86,7 @@
|
||||
>
|
||||
> 注:该比喻来自与网友 ryan0414,看到的时候,不禁惊呼可太贴切了!
|
||||
|
||||
### **n = 1004**
|
||||
### **n = 1004**
|
||||
|
||||
我们想要计算出**小于等于 1004 的非负整数中**,十位上出现 1 的次数。
|
||||
|
||||
@@ -103,13 +94,13 @@
|
||||
|
||||

|
||||
|
||||
> 解析:为什么我们可以直接通过高位数字 * num,得到 1 出现的次数
|
||||
> 解析:为什么我们可以直接通过高位数字 \* num,得到 1 出现的次数
|
||||
>
|
||||
> 因为我们高位为 10,可变范围为 0 ~ 10,但是我们的十位为 0 ,所以高位为 10 的情况取不到,所以共有 10 种情况。
|
||||
>
|
||||
> 又当前位为十位,低位共有 1 位,可选范围为 0 ~ 9 共有 10 种情况,所以直接可以通过 10 * 10 得到。
|
||||
> 又当前位为十位,低位共有 1 位,可选范围为 0 ~ 9 共有 10 种情况,所以直接可以通过 10 \* 10 得到。
|
||||
|
||||
其实不难理解,我们可以设想成行李箱的密码盘,在一定范围内,也就是上面的 0010 ~ 0919 , 固定住一位为 1 ,只能移动其他位,看共有多少种组合。
|
||||
其实不难理解,我们可以设想成行李箱的密码盘,在一定范围内,也就是上面的 0010 ~ 0919 , 固定住一位为 1 ,只能移动其他位,看共有多少种组合。
|
||||
|
||||
好啦,这个情况我们已经搞明白啦,下面我们看另一种情况。
|
||||
|
||||
@@ -119,21 +110,21 @@
|
||||
|
||||
也就是当前位为十位,数字为 1 时,十位上出现 1 的次数。
|
||||
|
||||
我们在小于 1014 的非负整数中,十位上为 1 的最小数字为 10,最大数字为 1014,所以我们需要在 10 ~ 1014 这个范围内固定住十位上的 1 ,移动其他位。
|
||||
我们在小于 1014 的非负整数中,十位上为 1 的最小数字为 10,最大数字为 1014,所以我们需要在 10 ~ 1014 这个范围内固定住十位上的 1 ,移动其他位。
|
||||
|
||||
其实然后我们可以将 1014 看成是 1004 + 10 = 1014
|
||||
|
||||
则可以将 10 ~ 1014 拆分为两部分 0010 ~ 0919 (小于 1004 ),1010 ~ 1014。
|
||||
则可以将 10 ~ 1014 拆分为两部分 0010 ~ 0919 (小于 1004 ),1010 ~ 1014。
|
||||
|
||||
见下图
|
||||
|
||||

|
||||
|
||||
> 解析:为什么我们可以直接通过 高位数字 * num + 低位数字 + 1 即 10 * 10 + 4 + 1
|
||||
> 解析:为什么我们可以直接通过 高位数字 _ num + 低位数字 + 1 即 10 _ 10 + 4 + 1
|
||||
>
|
||||
> 得到 1 出现的次数
|
||||
>
|
||||
> 高位数字 * num 是得到第一段的次数,第二段为 低位数字 + 1,求第二段时我们高位数字和当前位已经固定,
|
||||
> 高位数字 \* num 是得到第一段的次数,第二段为 低位数字 + 1,求第二段时我们高位数字和当前位已经固定,
|
||||
>
|
||||
> 我们可以改变的只有低位。
|
||||
|
||||
@@ -147,11 +138,9 @@
|
||||
|
||||
我们也可以将其拆成两段 0010 ~ 0919,1010 ~ 1019
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
> 解析:为什么我们可以直接通过高位数字 * num + num, 10 * 10 + 10 得到 1 出现的次数
|
||||
> 解析:为什么我们可以直接通过高位数字 _ num + num, 10 _ 10 + 10 得到 1 出现的次数
|
||||
>
|
||||
> 第一段和之前所说一样,第二段的次数,我们此时已经固定了高位和当前位,当前位为 1,低位可以随意取值,上诉例子中,当前位为 10,低位为位数为 1,则可以取值 0 ~ 9 的任何数,则共有 10 (num) 种可能。
|
||||
|
||||
@@ -161,12 +150,10 @@
|
||||
|
||||
> 注:蓝色高位,橙色当前位,绿色低位
|
||||
>
|
||||
> 初始化:low = 0, cur = n % 10, num = 1, count = 0, high = n / 10;
|
||||
> 初始化:low = 0, cur = n % 10, num = 1, count = 0, high = n / 10;
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
好啦,下面我们看一下题目代码吧
|
||||
|
||||
注:下方代码没有简写,也都标有注释,大家可以结合动画边思考边阅读。
|
||||
@@ -225,7 +212,7 @@ class Solution {
|
||||
}
|
||||
```
|
||||
|
||||
时间复杂度 : O(logn) 空间复杂度 O(1)
|
||||
时间复杂度 : O(logn) 空间复杂度 O(1)
|
||||
|
||||
C++ Code:
|
||||
|
||||
@@ -260,4 +247,4 @@ public:
|
||||
return count;
|
||||
}
|
||||
};
|
||||
```
|
||||
```
|
||||
|
Reference in New Issue
Block a user