1,从1到整数n中1出现的次数
思路:若百位上数字为0,百位上可能出现1的次数由更高位决定;若百位上数字为1,百位上可能出现1的次数不仅受更高位影响还受低位影响;若百位上数字大于1,则百位上出现1的情况仅由更高位决定。
举例:
①534
个位1出现的次数:round*1+1
(每次循环1出现一次,0-9循环了53次,第54次循环为0-4)
十位1出现的次数:round*10 + 10(每次循环1出现10次,0-9循环了round=5次,第六次循环为0-3)
其他高位循环同理。
故有:
534 = (个位1出现次数)+(十位1出现次数)+(百位1出现次数)
=(53*1+1) +(5*10+10)+(0*100+100) = 214
530 = (53*1) +(5*10+10)+(0*100+100) = 213
504 = (50*1+1)+(5*10) +(0*100+100) = 201
514 = (51*1+1)+(5*10+4+1)+(0*100+100) = 207
10 = (1*1) + (0*10+0+1) = 2
代码如下:
public long CountOne(int n) {
int count = 0; // 1的个数
int i = 1; // 当前位
int current = 0, after = 0, before = 0;
while ((n / i) != 0) {
before = n / (i * 10); // 高位
current = (n / i) % 10; // 当前位
after = n - (n / i) * i; // 低位
if (current == 0)
//如果为0,出现1的次数由高位决定,等于高位数字 * 当前位数
count = count + before * i;
else if (current == 1)
//如果为1,出现1的次数由高位和低位决定,高位*当前位+低位+1
count = count + before * i + after + 1;
else if (current > 1)
// 如果大于1,出现1的次数由高位决定,(高位数字+1)* 当前位数
count = count + (before + 1) * i;
//前移一位
i = i * 10;
}
return count;
}
2,丑数
丑数是只包含因子2、3和5的数,求从小到大的第N个丑数。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
思路一:
丑数判断:
boolean isUgly(int number) {
while (number % 2 == 0) number /= 2;
while (number % 3 == 0) number /= 3;
while (number % 5 == 0) number /= 5;
return number == 1 ? true : false;
}
然后依次输入每个数就可以获得N个丑数。但这样计算太多,即使一个数不是丑数,也要进行多次计算。
思路二:空间换时间,创建数组存储已经找到的丑数。后序的丑数都是min乘2或3或5得到的。
初始化数组只:{1} ;min = 1,后序 乘2或3或5,之后比较取最小值:2,3,5
public int GetUglyNumber_Solution(int index) {
if (index <= 0)
return 0;
int[] arr = new int[index];
arr[0] = 1;
int multiply2 = 0;
int multiply3 = 0;
int multiply5 = 0;
for (int i = 1; i < index; i++) {
int min = Math.min(arr[multiply2] * 2, Math.min(arr[multiply3] * 3, arr[multiply5] * 5));
arr[i] = min;
if (arr[multiply2] * 2 == min)
multiply2++;
if (arr[multiply3] * 3 == min)
multiply3++;
if (arr[multiply5] * 5 == min)
multiply5++;
}
return arr[index - 1];
}