20200310
题目 :1~n整数中1出现的次数。
输入一个整数n
,求1~n
这n个整数的十进制表示中1出现的次数。
例如,输入12,1~12这些整数中包含1 的数字有1、10、11和12,1一共出现了5次。
思路 :
f(n)
函数的意思是1~n
这n
个整数的十进制表示中1
出现的次数,将n
拆分为两部分,最高一位的数字high
和其他位的数字last
,分别判断情况后将结果相加,看例子更加简单。
例子如n=1234
,high=1
, pow=1000
, last=234
可以将数字范围分成两部分1~999
和1000~1234
1~999
这个范围1的个数是f(pow-1)
1000~1234
这个范围1的个数需要分为两部分:
千分位是1的个数:千分位为1的个数刚好就是234+1(last+1)
,注意,这儿只看千分位,不看其他位
其他位是1的个数:即是234
中出现1的个数,为f(last)
所以全部加起来是f(pow-1) + last + 1 + f(last)
;
例子如3234
,high=3
, pow=1000
,last=234
可以将数字范围分成两部分1~999
,1000~1999
,2000~2999
和3000~3234
1~999
这个范围1的个数是f(pow-1)
1000~1999
这个范围1的个数需要分为两部分:
千分位是1的个数:千分位为1的个数刚好就是pow
,注意,这儿只看千分位,不看其他位
其他位是1的个数:即是999
中出现1的个数,为f(pow-1)
2000~2999
这个范围1的个数是f(pow-1)
3000~3234
这个范围1的个数是f(last)
所以全部加起来是pow + high*f(pow-1) + f(last)
;
code
class Solution{
public int countDigitOne(int n){
return dfs(n);
}
private int dfs(int n){
if(n <= 0){
return 0;
}
String s = String.valueOf(n);
int high = s.charAt(0) - '0';
int pow = (int)Math.pow(10,s.length()-1);
int last = n - high*pow;
if(high == 1){
return dfs(pow-1) + last + 1 + dfs(last);
}else{
return pow + high*dfs(pow-1) + dfs(last);
}
}
}
题目 :数字序列中某一位的数字
数字以0123456789101112131415…的格式序列化到一个字符序列中。在这个序列中,第5位(从下标0开始计数)是5,第13位是1,第19位是4,等等。
请写一个函数,求任意第n位对应的数字。
思路 :找到序列第n位所在的是哪个数,然后是数的哪一位。
统计每位数有几个,如1位数有10,2位数有90*2…依次来找出所在的数
code :
class Solution{
public int findNthDigit(int n){
long[] count = new long[18];
count[1]=10;
long base = 90;
for(int i=2;i<18;i++){
count[i] = base*i;
base*=10;
}
int j=1;
while(n>count[j]){
n -= count[j];
j++;
}
if(n == 10) return 1;
if(j == 1) return n;
//他的j位数当中的第n/j个中的第n%j位(从左往右)
int jbase = 1;
for(int k=2;k<=j;k++){
jbase *=10;//j位数的第0个数
}
int jnum = jbase + n/j;//找到了所在的数。
int m=0;
for(int k=0;k<=n%j;k++){//从左往右找到n%j位
m=jnum/jbase;
jnum%=jbase;
jbase /= 10;
}
return m;
}
}
class Solution {
public int findNthDigit(int n) {
if (n < 10) {
return n;
}
int base = 1;
long count = 0; //计算有多少位,测试的时候发现有个1e9的用例,这个用例会导致count越界
while (true) {
count = helper(base);
if (n < count) break;
n -= count;
base++;
}
//得到新的n和count了,算出第n位对应什么数字
int num = (int) (n / base + Math.pow(10, base - 1));
return String.valueOf(num).charAt(n % base) - '0';
}
// 计算当前有多少位 1位数10种,10位;2位数 90个数字 180位;3位数 900个 2700位
private long helper(int base) {
if (base == 1) {
return 10;
}
return (long) (Math.pow(10, base - 1) * 9 * base);
}
}
来源:CSDN
作者:jjxwj
链接:https://blog.csdn.net/qq_31900497/article/details/104770072