算法的学习笔记—数字序列中的某一位数字(牛客JZ44)
😀前言
在编程面试中,遇到的问题往往需要我们高效处理大规模的数据或序列。今天我们要讨论的是一个典型的问题:如何在一个连续的数字序列中找到指定位置的数字。
😀数字序列中的某一位数字
数字序列中某一位的数字_牛客题霸_牛客网 (nowcoder.com)
问题描述
给定一个序列,它是由所有非负整数按顺序排列而成,如 0123456789101112131415...
。现在,给定一个索引 index
,我们需要找到这个序列中第 index
位的数字。
示例
- 输入:
index = 5
- 输出:
5
在序列 012345678910111213...
中,第 5 位对应的数字正是 5
。
😊解题思路
要解决这个问题,首先要认识到直接生成整个序列并索引显然不可行,因为生成的字符串会非常大。因此,我们需要找到一种不需要生成整个序列的方式,直接定位到我们需要的数字。
我们可以将序列分为不同的段,每一段由固定位数的数字组成。举个例子:
1
位数:0, 1, 2, ..., 9
(共有10
个数字)2
位数:10, 11, 12, ..., 99
(共有90
个数字)3
位数:100, 101, ..., 999
(共有900
个数字)
🥰具体实现
1. 找到目标所在的位数段
首先,我们需要确定目标数字所在的位数段。例如,如果索引在 1
位数范围内,我们直接返回对应数字即可;如果不在,则将索引减去这一段的长度,继续判断它是否在 2
位数段,依此类推。
2. 计算该段中具体的数字
确定了位数段后,我们可以计算出目标数字具体是该段中的哪个数字。通过简单的除法计算可以得到它是该段中的第几个数字。
3. 提取数字的具体位置
最后,在确定了具体的数字后,我们可以提取它在字符串中的具体位置。
以下是代码实现:
public int getDigitAtIndex(int index) {
if (index < 0)
return -1;
int place = 1; // 1 表示个位,2 表示 十位...
while (true) {
int amount = getAmountOfPlace(place);
int totalAmount = amount * place;
if (index < totalAmount)
return getDigitAtIndex(index, place);
index -= totalAmount;
place++;
}
}
/**
* place 位数的数字组成的字符串长度
* 10, 90, 900, ...
*/
private int getAmountOfPlace(int place) {
if (place == 1)
return 10;
return (int) Math.pow(10, place - 1) * 9;
}
/**
* place 位数的起始数字
* 0, 10, 100, ...
*/
private int getBeginNumberOfPlace(int place) {
if (place == 1)
return 0;
return (int) Math.pow(10, place - 1);
}
/**
* 在 place 位数组成的字符串中,第 index 个数
*/
private int getDigitAtIndex(int index, int place) {
int beginNumber = getBeginNumberOfPlace(place);
int shiftNumber = index / place;
String number = (beginNumber + shiftNumber) + "";
int count = index % place;
return number.charAt(count) - '0';
}
代码解析
- getDigitAtIndex(int index):这个方法是主函数,负责找到对应的数字。我们首先确定数字的位数段,然后进入这个段查找具体的数字。
- getAmountOfPlace(int place):这个方法计算当前位数段的数字个数。例如,
1
位数段有10
个数字(0 到 9),2
位数段有90
个数字(10 到 99)。 - getBeginNumberOfPlace(int place):这个方法返回当前位数段的起始数字。例如,
1
位数段从0
开始,2
位数段从10
开始。 - getDigitAtIndex(int index, int place):这个方法根据索引计算出目标数字,并返回它在目标字符串中的具体位置。
😄总结
通过上述步骤,我们可以在不需要生成完整序列的前提下,快速定位并获取任意索引位置的数字。该方法时间复杂度为 O(log n)
,适用于处理大规模数据。无论是在实际开发中,还是在面试中,这种解题思路都具有较高的实用性。
- 点赞
- 收藏
- 关注作者
评论(0)