【数学知识】剑指 Offer 44. 数字序列中某一位的数字

本问题对应课程链接:剑指offer刷题第三期

要求:
1、请打卡你的解题代码,如果能简单说一下思路则简单说一下思路。
2、给出你代码所用的时间复杂度和空间复杂度

共以下 19 个回答

  • 九号球 普通 2023年11月23日 下午8:57

    “`java
    class Solution {
    public int findKthNumber(int k) {
    //一位数、两位数、三位数到n位数,它们的位数为digit,开始值为start,则它们数字的数量为9*start,数位数量为9*start*digit
    int digit = 1;
    long start = 1;
    long count = 9;
    //首先找出第k位应该位于几位数的数字上
    while (k > count) {
    //每次执行相当于把前一个n位数的范围数量减掉
    k -= count;
    start *= 10;
    digit += 1;
    count = 9 * start * digit;
    }
    //找出k应该位于哪个数字上,因为剩余的数字的位数都是digit,所以k的落到的数字为
    long num = start + (k – 1)/digit;
    //找出k位于数字的第几位
    int index = (k-1)%digit;
    return String.valueOf(num).charAt(index) – ‘0’;
    }
    }

    0 赞同 0 条回复
  • 招舟子 普通 2023年9月7日 下午5:08

    class Solution {
    public int findNthDigit(int n) {
    //先求多少位数
    long bit = 1;
    int i=1;
    long count =9;
    while(n>count){
    n=(int)(n-count);
    bit=bit10;
    i=i+1;
    count = 9
    bit*i;
    }
    //哪个数
    long num = bit+(n-1)/i;
    //第几位
    int index = (n-1)%i;
    return Long.toString(num).charAt(index)-‘0’;
    }
    }

    0 赞同 0 条回复
  • 彦,,# 普通 2023年8月5日 下午3:55
    官方
    int countDigitOne(int n) {
            long long mulk = 1;
            int ans = 0;
            for(int k = 0;n >= mulk; ++k){
                ans += (n/(mulk * 10)) * mulk + min(max(n %(mulk * 10) - mulk +1, 0ll ),mulk);
                mulk *= 10;
            }
            return ans;
        }
    
    0 赞同 0 条回复
  • mpweixin用户 普通 2023年8月1日 上午11:00
    java
    class Solution {
        public int findNthDigit(int n) {
            if(n == 0) {
                return 0;
            }
            int digit = 1; //表示位的个数,如1000表示有4位
            long start = 1; //表示起始的数值
            long count = 9 * start * digit;
    
            //先求出n在1-9, 10-99, 100-999,...,哪个区间
            while(n > count) { 
                n -= count;
                digit ++;
                start *= 10;
                count = 9 * start * digit;
            }
    
            //求出n所在区间是哪个数
            long num = start + (n -1) / digit;
            //求出n所在这个数的哪一位
            int index = (n-1) % digit + 1;
            return (int)(num / Math.pow(10, digit - index) % 10);
        }
    }
    

    时间复杂度O(logN), 空间复杂度O(1)

    0 赞同 0 条回复
  • 屠龙手段 普通 2023年7月22日 下午11:03

    找规律,时间复杂度O(logn) 空间复杂度(1)

    class Solution {
    public:
        int findNthDigit(int n) {
            if(n < 10) return n;
            long long start = 1, digit = 1;
            long long cnt = 9;
            int tmp = n;
            while(tmp > cnt){
                tmp -= cnt;
                start *= 10;
                digit += 1;
                cnt = 9 * start * digit;
            }
            long long num = (tmp - 1) / digit + start;
            long long num_digit = (tmp - 1) % digit;
            return num / (int)pow(10, (int)log10(num) - num_digit) % 10;
        }
    };
    
    0 赞同 0 条回复
  • 怀瑾 永久会员 2023年7月19日 下午3:32

    “`C++
    int findNthDigit(int n) {
    if (n < 0) return -1;

    int digits = 1;  // 当前数字的位数
    long long count = 9; // 当前位数的数字总数
    int start = 1; // 当前位数的起始数字
    
    // 找到n所在的数字的位数
    while (n > digits * count) {
        n -= digits * count;
        digits++;
        count *= 10;
        start *= 10;
    }
    
    // 找到n所在的数字
    int num = start + (n - 1) / digits;
    
    // 找到n对应的数字的第几位
    int digitPos = (n - 1) % digits;
    
    // 找到n对应的数字的第digitPos位上的数字
    return std::to_string(num)[digitPos] - '0';
    

    }

    “`

    0 赞同 0 条回复
  • 憨憨 永久会员 2023年7月19日 下午12:27

    找位数跟长度之间的额规律

    class Solution {
        public int findNthDigit(int n) {
            if(n == 0)return 0;
            long id = 1;
            long res = 0;
            while(res < n){
                res = res + id * 9 *(int)Math.pow(10,id-1);
                id++;
            }
            id--;
            res = 0;
            for(int i =1;i < id ; i ++){
                res = res + i * 9 *(int)Math.pow(10,i-1);
            }
            res = n - res;
            long num = res / id;
            long mod = res % id;
    
    
            long ans = 0;
            if(mod == 0){
                ans = (long)Math.pow(10,id-1) - 1;
                ans += num;
            }else{
                ans = (long)Math.pow(10,id-1) - 1;
                ans += num + 1;
                for(int i = 0; i < id - mod;i++ ){
                    ans /= 10;
                }
            }
            return (int)ans%10;
        }
    }
    
    0 赞同 0 条回复
  • 名字什么的好麻烦 普通 2023年7月16日 下午9:21

    找规律

    class Solution {
        public int findNthDigit(int n) {
            int digit=1;
            long start=1;
            long count=9;
            while(n>count){
                n-=count;
                digit++;
                start<em>=10;
                count=digit</em>start*9;
            }
            long num=start+(n-1)/digit;
            return Long.toString(num).charAt((n-1)%digit)-'0';
        }
    }
    
    
    0 赞同 0 条回复
  • 哈哈哈哈开开心心 普通 2023年7月16日 上午4:36
    class Solution:
        def findNthDigit(self, n: int) -> int:
            bit = 1
            i = 1
            cnt = 9
    
            while cnt < n:
                n -= cnt
                i += 1
                bit *= 10
                cnt = bit * i * 9
    
            # 数
            num = bit + (n - 1) // i
    
            # 位
            idx = (n - 1) % i + 1
    
            res = (num // (10 ** (i - idx))) % 10
            return res
    
    0 赞同 0 条回复
  • BOZ 普通 2023年7月15日 下午5:27

    【思路】考虑一位数,二位数,三位数…的数字数量以及字符长度,最终找到对应的数字
    【复杂度】时间O(logn),空间O(1)

    class Solution {
    public:
        int findNthDigit(int n) {
            if (n < 10) return n;
    
            int level = 1;
            int num = 0;
            while (true) {
                int current_level_num = 9 * std::pow(10, level - 1);
                if (level < 9 && n >= current_level_num * level) {
                    num += current_level_num;
                    n -= current_level_num * level;
                    level++;
                } else break;
            }
    
            num += n % level? n / level + 1: n / level;
            level = n % level? level - n % level: 0;
            num /= std::pow(10, level);
            return num % 10;
        }
    };
    
    0 赞同 0 条回复
  • 花老爷 普通 2023年7月14日 下午10:25

    官解
    时间:O(logn)
    空间:O(1)

    class Solution {
        public int findNthDigit(int n) {
            int d = 1, count = 9;
            while (n > (long) d * count) {
                n -= d * count;
                d++;
                count *= 10;
            }
            int index = n - 1;
            int start = (int) Math.pow(10, d - 1);
            int num = start + index / d;
            int digitIndex = index % d;
            int digit = (num / (int)(Math.pow(10, d - digitIndex - 1))) % 10;
            return digit;
        }
    }
    
    0 赞同 0 条回复
  • Ming 普通 2023年7月13日 下午2:32

    时间复杂度:O(logn)
    额外空间复杂度:O(1)
    先确定n的区间是个位、百位还是千位等 n < count,
    再确定是哪一个数 bit+(n – 1) / i,
    再确定是哪一位(n – 1) %i+1;

    public int findNthDigit(int n) {
            if(n == 0) return 0;
    
            long bit = 1;
            int i = 1;
            long count = 9;
            while(count < n) {
                n = (int)(n - count);
                bit = bit * 10;
                i++;
                count = bit * i * 9;
            }
    
            long num = bit + (n - 1) / i;
            int index = (n - 1) % i + 1;
            int res = (int)(num / Math.pow(10, i - index) % 10);
            return res;
        }
    
    0 赞同 0 条回复
  • Dsjh 普通 2023年7月11日 上午10:38

    MY

    class Solution {
    public:
        int findNthDigit(int n) {
            int ans=0;
            if(n==0){
                return 0;
            }
            // 哪个范围 
            long b=1; // 使 b*num 合法
            int num=9;
            while(n>(b*num)){
                n = n-(b*num);            
                b++;
                num *= 10;            
            }        
            // 范围中的哪个数
            int start=1;
            for(int i=0;i<b-1;i++){
                start *= 10;
            }
            int tar = n/b;
            int mod = n%b;
            if(mod == 0){
                tar = start + tar - 1;
                string temp = to_string(tar);
                ans = temp.back()-'0';
            }
            else{
                tar = start + tar;
                string temp = to_string(tar);
                ans = temp[mod-1]-'0';
            }
            return ans;
        }
    };
    
    0 赞同 0 条回复
  • 局外人 普通 2023年7月10日 下午11:52

    思想:按照不同位数范围,寻找数学规律,
    时间复杂度:O(logn) 空间复杂度:O(1)

    class Solution {
        public int findNthDigit(int n) {
    
            int digit = 1;
            long start = 1;
            long count = 9;
    
            while(n>count){
                n -= count;
                digit += 1;
                start *= 10;
                count = digit*start*9;
            }
    
            long num = start + (n-1)/digit;
            return Long.toString(num).charAt((n-1)%digit)-'0';
        }
    }
    
    0 赞同 0 条回复
  • Vow the vow。 普通 2023年7月10日 上午11:35

    看大佬解析

    public int findNthDigit(int n) {
            // start:起始数字;count:数位; digit:位数
            long start = 1, count = 9;
            int digit = 1;
            int preCount = 0;
            // 1. 确定n所在数位 count
            while(n > count){
                n -= count;
                digit++;  
                start *= 10;;
                count = 9 * start * digit;
            }
            // 2. 确定n所在数字
            long num = start + (n-1)/digit;
            // 3. 确定所求数位在数字的哪一位 (n-1)%digit
            int res = Long.toString(num).charAt((n-1)%digit) - '0';
            return res;
        }
    
    0 赞同 0 条回复
  • mpweixin用户 永久会员 2023年7月9日 下午9:51
    //时间O(logn)  空间O(1)
    public int findNthDigit(int n) {
        if (n <= 9)
            return n;
        int digits = 1;     //当前数位---1位数
        long begin = 1;     //1位数,从1开始
        long count = 10;    //从0到所有的1位数,一共10个。
        while (n > count) {
            n -= count;     //减去前面的字符数
            digits++;       //位数+1---2位数
            begin *= 10;    //开始数*10---从10开始
            count = digits * begin * 9; //所有2位数有多少个“字符”---180个
        }
        long num = begin + n / digits;  //(n / digits)算出我是当前范围的第几个
        return Long.toString(num).charAt(n % digits) - '0'; //取出对应字符减'0'字符(48),得到具体数字
    }
    
    0 赞同 0 条回复
  • yxy 普通 2023年7月9日 下午5:27

    时间复杂度O(log10n)

    class Solution {
    public:
        int findNthDigit(int n) {
            if(n==0) return 0;
            long long i=1,base = 1,num =9;//i表示是几位数,base表示位数的起始值, num表示位数共有多少个
            //第一步
            while(n>i*num)
            {
                n-=i*num;
                i++;
                num*=10;
                base*=10;
            }
            //此时i表示n是落在几位数群体里的
    
            //第二步
            int number = base + (n+i-1)/i - 1; //number为n在number这个数里面
    
            //第三步
            if(n%i==0)
                return number%10;
            else
            {
                int r = n%i;
                r = i-r;
                while(r--)
                    number/=10;
                return number%10;
            }
        }
    };
    
    0 赞同 0 条回复
  • 张开怀 普通 2023年7月9日 下午4:25
    class Solution{
    public:
           int findNthDigit(int n){
                  if(n==0){
                         return 0;
                  }
                  long bit =1;
                  int i = 1;
                  long count = 9;
                  while(count < n){
                         n = n -count;
                         bit =bit * 10;
                         i++;
                         count = bit * i *9;
                  }
                  // 确定是在这个区间的哪个数
                  long num = bit + (n -1) / i;
                  // 确定在num 的那个字符
                  int index = (n-1)%i+1;
                  int res =(int)(num/pow(10,i-index))%10;
    
                  return res;
           }
    };
    

    时间复杂度:O(logn)
    额外空间复杂度:O(1)

    0 赞同 0 条回复
  • Yodl. 普通 2023年7月9日 下午3:54
    //时间复杂度O(n) 空间复杂度O(1)
    class Solution {
    public:
        int findNthDigit(int n) {
            int k = 1;
            while (cal_Lk(k) < n) {
                n -= cal_Lk(k); // 这样 n 中保留的就是残余位
                k++;
            }
            long long knum = pow(10, k - 1) + n / k - 1;  // 第 n / k 个 k 位数
            n -= n / k * k; // 在这个 k 位数的第几位
            if (n == 0)
                return (knum) % 10;
            else
                return to_string(knum + 1)[n - 1] - '0';
        }
    private:
        long long cal_Lk(int k) {
            return (long long) 9 * k * pow(10, k - 1);
        }
    };
    
    0 赞同 0 条回复

# 回答此问题

后才能回答