JS算法之1~n整数中1出现的次数及数字序列中某一位的数字

192 阅读1分钟

这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战

1~n整数中1出现的次数

剑指Offer 43.1~n整数中1出现的次数

难度:困难

题目:leetcode-cn.com/problems/1n…

输入一个整数n,求1~n这n个整数的十进制表示中1出现的个数。

例如,输入12,1~12这些整数中包含1的数字有1、10、11和12,1一共出现了5次。

示例1:

输入:n = 12
输出:5

示例2:

输入:n = 13
输出:6

限制:1 <= n < 2^31

题解

归纳法

这道题纯用归纳解决

从个数到最高位遍历,将n看成「high、cur、low」这三个部分,其中cur为当前位数,high为cur之前的值,low为cur之后的值,根据当前位数,设digit为1、10、100......通过数学归纳法推理出:

  • cur = 0,执行res += high * digit
  • cur = 1,执行res += high * digit + low + 1
  • cur > 1,执行res += high * digit + digit
/**
 * @param {number} n
 * @return {number}
 */
var countDigitOne = function (n) {
  let digit = 1,
    res = 0;
  let high = Math.floor(n / 10),
    cur = n % 10,
    low = 0;
  while (high !== 0 || cur !== 0) {
    if (cur === 0) res += high * digit;
    else if (cur === 1) res += high * digit + low + 1;
    else res += high * digit + digit;
    low += cur * digit;
    cur = high % 10;
    high = Math.floor(high / 10);
    digit *= 10;
  }
  return res;
};
  • 时间复杂度:O(logNlogN)
  • 空间复杂度:O(11)

数字序列中某一位的数字

剑指Offer 44.数字序列中某一位的数字

难度:中等

题目:leetcode-cn.com/problems/sh…

数字以0123456789101112131415...的格式序列化到一个字符序列中。在这个序列中,第5位(从下标0开始计数)是5,第13位是1,第19位是4,等等。

请写一个函数,求任意第n位对应的数字。

示例1:

输入:n = 3
输出:3

示例2:

输入:n = 11
输出:0

限制:0 <= n < 2^31

题解

找规律

将101112...中的每一位称为数位n,将10,11,12...称为数字num,每digit位数的起始数字(1,10,100...)称为start。

数字氛围位数digit数字数量数位数量
1~9199
10~99290180
100~99939002700
............
start~enddigit9 * start9 * start * digit

由表格得出:

  • digit = digit + 1
  • start = start * 10
  • count = 9 * start * digit

求解思路:

  • 确定n所在数字的位数,即digit
  • 确定n所在的数字,即num
  • 确定n是num中的哪一数位,并返回结果
  1. 确定n所在位数:
数字氛围位数数位数量n = n - count
1~919n - 9
10~992180n - 9 -180
100~99932700n - 9 - 180 -2700
start~enddigit9 * start * digit直至n <= count

由表格得出:

  • 所求位数在某个digit位数中
  • 所求位数为从数字start开始的第n个位数
  1. 确定n所在的数字

digit = 2,start = 10

101112...
n123456...
(n - 1)012345...
(n - 1) / 2001122...

由表格得出:

  • 数字num = start + (n - 1) / digit
  1. 确定n是num中的哪一数位
101112...
n123456...
(n - 1)012345...
(n - 1) % 2010101...

由表格得出:

  • 所求数位在num的第(n - 1) % 2位

整体实现代码如下:

/**
 * @param {number} n
 * @return {number}
 */
var findNthDigit = function (n) {
  let digit = 1,
    start = 1,
    count = 9;
  while (n > count) {
    n -= count;
    digit += 1;
    start *= 10;
    count = digit * start * 9;
  }
  let num = Math.floor(start + (n - 1) / digit);
  return Number(num.toString(10)[(n - 1) % digit])
};

坚持每日一练!前端小萌新一枚,希望能点个哇~