【剑指offer】【数学】43. 1~n整数中1出现的次数
题目链接:https://leetcode-cn.com/problems/1nzheng-shu-zhong-1chu-xian-de-ci-shu-lcof/
按位统计
以abcdef为例,固定其中一位为1,然后统计:
0 ~ ab - 1:
左边:ab:00 ~ ab - 1, ab个
右边:def: 000 ~ 999, 1000个
总数: ab * 1000
ab:
c = 0: 0
c = 1: 0 ~ def; def + 1个
c > 1: 000 ~ 999;1000个
时间复杂度:O(log(n^2)) 以10为底
空间复杂度:O(logn)
class Solution {
public:
int countDigitOne(int n) {
if(!n) return 0;
vector<int> number;
while(n) number.push_back(n % 10), n /= 10;
long long res = 0;
for(int i = number.size() - 1; i >= 0; i--)
{
int left = 0, right = 0, t = 1;
for(int j = number.size() - 1; j > i; j-- )
left = left * 10 + number[j];
for(int j = i - 1; j >= 0; j --)
right = right * 10 + number[j], t *= 10;
res += left * t;
if(number[i] == 1) res += right + 1;
else if(number[i] > 1) res += t;
}
return res;
}
};
优化
思路与上面一样,不过不用 vector来存储数字了,直接计算;
时间复杂度:O(log(n)) 以10为底
空间复杂度:O(1)
class Solution {
public:
int countDigitOne(int n) {
if(!n) return n;
int res = 0, t = 1, m = n;
while(m > 0)
{
t *= 10;
// 当前位左边的数
int left = n / t;
//当前位的数
int cur = (n % t) / (t / 10);
//当前位右边的数
int right = (n % t) % (t / 10);
m /= 10;
res += left * t / 10;
if(cur == 1) res += right + 1;
if(cur > 1) res += t / 10;
}
return res;
}
};
知识的价值不在于占有,而在于使用