Find the nth digit(二分查找) - HDU 1597
Posted ACM算法日常
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Find the nth digit(二分查找) - HDU 1597相关的知识,希望对你有一定的参考价值。
拜个晚年~祝各位2018新年快乐!狗年旺旺!
Problem Description
假设:
S1 = 1
S2 = 12
S3 = 123
S4 = 1234
.........
S9 = 123456789
S10 = 1234567891
S11 = 12345678912
............
S18 = 123456789123456789
..................
现在我们把所有的串连接起来
S = 1121231234.......123456789123456789112345678912.........
那么你能告诉我在S串中的第N个数字是多少吗?
Input
输入首先是一个数字K,代表有K次询问。
接下来的K行每行有一个整数N(1 <= N < 2^31)。
Output
对于每个N,输出S中第N个对应的数字.
Sample Input
6
1
2
3
4
5
10
Sample Output
1
1
2
1
2
4
题意容易理解,但是做到高效需要注意二分查找的写法。
关于二分检索:
二分检索的思想是每次把范围缩小一半。例如,你需要在一个从小到大有 序的有15个元素的线性表中查找数11 ,而已知第8个数是“6”,“11”如果在 表中,那么它一定在第9个数〜第15个数这个范围之内。
解题说明:
本题只是使用常规的二分查找,由于没有使用递归,性能会好很多。本题最关键的地方在于使用了一张表保存所有的位置信息,进而进行区间划分,使得后面能够使用二分查找解题。
源码:G++ 0ms
#include <stdio.h>
int main()
{
//静态存储区默认值为0,66000是调整的值,只要不WA,可以尝试从大往小调
static int sum[66000];
int index;
int position;
//初始化表,这张表记录了每个区间的位置
//0,1(0+1),3(1+2),6(3+3)...
for (int i = 1; i < 66000; ++i) {
sum[i] = sum[i - 1] + i;
}
int count;
scanf("%d", &count);
while (count--) {
scanf("%d", &position);
index = -1;
int l = 1;
int r = 66000;
//二分查找
while (1) {
//每次进来算出新的中间位置
int mid = (l + r) / 2;
//正好在区间里面,注意这里是index=mid
if (sum[mid] < position && sum[mid + 1] >= position) {
index = mid;
break;
}
//如果在左区间,则将r指针指向中间
if (position <= sum[mid])
r = mid - 1;
//如果在右区间,则将l指针指向中间
if (sum[mid + 1] < position)
l = mid + 1;
}
//n为位置,减去区间值,则是剩余的值,如101,如果区间值为90
//则剩余11,这个11代表的肯定是12345678912这样的串
int value = position - sum[index];
//取余,去掉1-9这样的重复串
value %= 9;
if (value == 0) {
value = 9;
}
printf("%d\n", value);
}
}
以上是关于Find the nth digit(二分查找) - HDU 1597的主要内容,如果未能解决你的问题,请参考以下文章