可以理解为用一个标签,将数字分成两部分,left,right。
可以理解为将这一位置1,左右有多少种组合
以233 为例
百 | 十 | 个 | left可取的数字 | right可取的数字 | 可以有多少组合 |
---|---|---|---|---|---|
2 | 3 | 3 | —— | —— | 原始数据 |
—— | —— | cur | 00-23 | 0 | 共24种(left + 1) |
—— | cur | —— | 0-2 | 0-9 | 左右排列组合共30种 =(left + 1) * 位值) |
cur | —— | —— | 0 | 0-99 | 排列组合100种(right + 1) |
public class Solution {
//注意求的不是包含1的数字有多少个,而是1出现的次数,那么11算2次
public int NumberOf1Between1AndN_Solution(int n) {
int count = 0;
//cur 代表个位,10位,百位,千位
for (int cur = 1; cur <= n; cur *= 10) {
//求出左右两边的值
int left = n / (cur * 10);
int right = n % cur;
int pointer = n / cur % 10;
if (pointer > 1) {
//cur 位大于1的话
//左边的数字组合数 left + 1
//右边的数字组合数 cur
count += (left + 1) * cur;
} else if (pointer == 0) {
//cur == 0 的话,要使得cur 位为1,必然需要向上借一位
count += left * cur;
} else {
//cur = 1 的话,要使cur位为1,当右边取最大值时,左边有上限
count += left * cur + right + 1;
}
}
return count;
}
}