题目链接: leetcode.
无论如何,没思路时一定要想到暴力
虽然超时 O(n*log10(n)) O(log10(n))
int countDigitOne(int n)
{
int countr = 0;
for (int i = 1; i <= n; i++) {
string str = to_string(i);
countr += count(str.begin(), str.end(), '1');
}
return countr;
}
//作者:LeetCode
//链接:https://leetcode-cn.com/problems/number-of-digit-one/solution/shu-zi-1-de-ge-shu-by-leetcode/
//来源:力扣(LeetCode)
//著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
本质上是一道数学题,要学会举"1"反"n"
个位为1的,每增加10个就出现1个:
(n/10) + (n%10 != 0)
,也就是(n/10)*1 + min(max(n%10 - 1 + 1, 0), 1)
十位为1的,每增加100个数就出现10个,剩下不到一百的,大于10就再加,最多加10个:
(n/100)*10 + min(max(n%100 - 10 + 1, 0), 10)
百位为1的,每增加1000个数就出现100个:
(n/1000)*100 + min(max(n%1000 - 100 + 1, 0), 100)
… …
/*
执行用时:0 ms, 在所有 C++ 提交中击败了100.00%的用户
内存消耗:5.6 MB, 在所有 C++ 提交中击败了99.00%的用户
*/
class Solution {
public:
int countDigitOne(int n) {
int ans = 0;
//i <= n,避免漏掉n==1
for(long long i = 1;i <= n;i *= 10)
{
ans += (n / (i * 10)) * i;
ans += min(max(n % (i * 10) - i + 1, 0LL), i);
// ans += min(max(n % (i * 10) - i + 1, (long long)0), i);
}
return ans;
}
};
在C和C++中,整数常量使用其原始类型求值,这可能会由于整数溢出而导致错误。后缀
LL
表示该常数是long long
类型,而UL
表示unsigned long
。