目录
刷题日期:下午8:00 2021年5月10日星期一
个人刷题记录,代码收集,来源皆为leetcode
经过多方讨论和请教,现在打算往Java方向发力
主要答题语言为Java
题目:
剑指 Offer 44. 数字序列中某一位的数字
难度中等119
数字以0123456789101112131415…的格式序列化到一个字符序列中。在这个序列中,第5位(从下标0开始计数)是5,第13位是1,第19位是4,等等。
请写一个函数,求任意第n位对应的数字。
示例 1:
输入:n = 3
输出:3
示例 2:
输入:n = 11
输出:0
限制:
0 <= n < 2^31
题目分析
和43题类似,都是涉及到位数,需要找规律的题,不过这个如果能通过举例子找到一定的公式来计算的话,就会简便很多。
也不能通过之前的乘除十来简化。
前十是本身,然后二位数有90个,三位数900个,四位数9000个……首要问题还是先判断出是多少位,然后进行计算。
肯定不能通过设置条件硬分,这样的话范围那么广肯定不行,因此还是得找到规律。
初始解答:
没什么思路,参考他人。
评论里也是一片抱怨,这种找规律的题感觉就是在考数学,而不是编程。
学习K神的分析:
class Solution {
public int findNthDigit(int n) {
int digit = 1; //位数,默认1
long start = 1; //该位数范围内的第一个数,10 100 1000等
long count = 9; //所占的位数,即尾,如果大于说明要一层一层增大寻找范围
while(n > count) {
n -= count; //大于尾则继续取差 9 180 2700
digit++;//同时说明位数要加一了
start *= 10;//同理
count = digit * start * 9; //同理尾也要扩大,9 99 999等
}
//这时已经确定是几位数了,而且已经把相应的尾减去了
//初步得到是在那个数里
long num = start + (n - 1) / digit;
//先转化为字符串类型,然后利用方法取对应位的值
//减一是因为从0数的,不减大一位,对位数取余就知道在这个数的第几个了
//要记住Java方法基本都是先小写再大写
return Long.toString(num).charAt((n - 1) % digit) - '0'; //精髓
}
}
太强了,执行结果:通过
显示详情 添加备注
执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:34.9 MB, 在所有 Java 提交中击败了99.27%的用户
学习他人:
比较恶心的题一般评论区里面人也不会多,这题的题解都没多少人写。
方法一:
Aurora 2020-05-11 Java 和K神的一模一样。
/* 数字范围 数量 位数 占多少位
1-9 9 1 9
10-99 90 2 180
100-999 900 3 2700
1000-9999 9000 4 36000 ...
例如 2901 = 9 + 180 + 2700 + 12 即一定是4位数,第12位 n = 12;
数据为 = 1000 + (12 - 1)/ 4 = 1000 + 2 = 1002
定位1002中的位置 = (n - 1) % 4 = 3 s.charAt(3) = 2;
*/
class Solution {
public int findNthDigit(int n) {
int digit = 1; // n所在数字的位数
long start = 1; // 数字范围开始的第一个数
long count = 9; // 占多少位
while(n > count){
n -= count;
digit++;
start *= 10;
count = digit * start * 9;
}
long num = start + (n - 1) / digit;
return Long.toString(num).charAt((n - 1) % digit) - '0';
}
}
方法二:
黑筋 2021-04-06
编程的第一法则:如果您的代码以某种莫名方式跑起来了,请不要在尝试修改它了
class Solution {
public int findNthDigit(int n) {
if(n==Integer.MAX_VALUE) return 2;//面向测试用例编程
int number = 0,p = 0;//number:第n位的实际数字,n为此数字的右数p位
for(int i=10,j=1;i<Integer.MAX_VALUE;i*=10,j++){
if(n/j>=i){//n=n+10+100+1000+......使得n=number*number的位数
n+=i;
}else{
number = n/j;
p = j-n%j-1;
break;
}
}
for(int k = 0;k<p;k++){
number/=10;
}
return number%10;
}
}
方法三:
K神: 解题思路:
- 将 101112 \cdots101112⋯ 中的每一位称为 数位 ,记为 n ;
- 将 10, 11, 12, \cdots10,11,12,⋯ 称为 数字 ,记为 num ;
- 数字 1010 是一个两位数,称此数字的 位数 为 22 ,记为 digit ;
- 每 digitdigit 位数的起始数字(即:1, 10, 100, \cdots1,10,100,⋯),记为 start。
作者:jyd
链接:https://leetcode-cn.com/problems/shu-zi-xu-lie-zhong-mou-yi-wei-de-shu-zi-lcof/solution/mian-shi-ti-44-shu-zi-xu-lie-zhong-mou-yi-wei-de-6/
来源:力扣(LeetCode)
class Solution {
public int findNthDigit(int n) {
int digit = 1;
long start = 1;
long count = 9;
while (n > count) { // 1.
n -= count;
digit += 1;
start *= 10;
count = digit * start * 9;
}
long num = start + (n - 1) / digit; // 2.
return Long.toString(num).charAt((n - 1) % digit) - '0'; // 3.
}
}
总结
以上就是本题的内容和学习过程了,属于找规律的数学题,能记住大概的思路,到时候推敲就行。
欢迎讨论,共同进步。