整数nを入力し、1からnまでのn個の整数の10進表現で1の出現回数を見つけます。
たとえば、12と入力すると、1から12までの整数に1を含む数字は、1、10、11、および12であり、1は合計5回表示されます。
例1:
输入:n = 12
输出:5
例2:
输入:n = 13
输出:6
制限:
1 <= n <2 ^ 31
注:この質問は、メインWebサイトの233の質問と同じです:https://leetcode-cn.com/problems/number-of-digit-one/
問題解決のアイデア:
特定の位置での1の発生数を計算する方法:
現在のビットの異なるcur値に応じて、次の3つの状況に分けることができます。
1. cur = 0の場合:このビット1の出現回数は、上位ビットの上位ビットによってのみ決定されます。計算式は、次の図に示すように、
上位×数字
です。n= 2304を例にとると、1を求めます。桁数= 10(つまり、10桁)出現回数。
2. cur = 1の場合:このビット1の出現回数は、上位ビットと下位ビットの下位によって決まります。計算式は、次の図に示すように、
high×digit + low +1
です。n= 2314を使用します。例として、digit = 10(つまり、10の位での1の出現回数)を見つけます。
3. cur = 2、3、...、9の場合:このビット1の出現回数は、上位ビットの上位ビットによってのみ決定されます。計算式は次のとおりです。
(high+1)×digit
次の図に示すように、n = 2324を例にとると、1桁の数字= 10(つまり、10の位)の出現数を見つけます。
class Solution {
public:
int countDigitOne(int n) {
long digit = 1;
int res = 0;
int high = n / 10, cur = n % 10, low = 0;//cur是n除以10的余数,后面的cur是high的余数
while(high != 0 || cur != 0) {
// 当 high 和 cur 同时为 0 时,说明已经越过最高位,因此跳出
if(cur == 0) res += high * digit;
else if(cur == 1) res += high * digit + low + 1;
else res += (high + 1) * digit;//
low += cur * digit;//low就是cur一轮一轮叠加得到;此处参数是用作下一轮
cur = high % 10;//cur是high的余数;;下一轮用
high /= 10;//high从右边减少一位;下一轮用
digit *= 10;//digit乘以10;下一轮用
}
return res;
}
};
複雑さの分析:
時間計算量O(log n):ループ内の計算操作はO(1)時間を使用します。ループの数は、数値nの桁数、つまりlog 10 nであるため、ループはO(log n)を使用します。 )時間。
スペースの複雑さO(1):いくつかの変数は一定サイズの余分なスペースを使用します。
著者:jyd
リンク:https://leetcode-cn.com/problems/1nzheng-shu-zhong-1chu-xian-de-ci-shu-lcof/solution/mian-shi-ti-43-1n-zheng-shu -zhong-1-chu-xian-de-2 /
出典:LeetCode(LeetCode)
著作権は作者に帰属します。商用の転載の場合は、著者に連絡して許可を求め、非商用の転載の場合は、出典を示してください。