描述:有一个十六进制序列由S1S2…Sk组成,其中Sk由1到k的十六进制数字依次组成。给定一个位置i,返回第i个位置上的字符。数字i为32位int。
例如,S1S2…Sk的前200个字符为
112123123412345123456123456712345678123456789123456789A123456789AB123456789ABC
123456789ABCD123456789ABCDE123456789ABCDEF123456789ABCDEF10123456789ABCDEF
1011123456789ABCDEF101112123456789ABCDEF10111213
所以i=50时,字符为5,i=100时,字符为9
要求时间复杂度小于O(n),空间复杂度O(1)
思路:先找出i落在哪个Sk序列上,再找出是在Sk序列的第几个数,最后找出是在这个数的第几位。
1. 对于每个Sk序列,先求出该序列的总字符个数。假设数字k用16进制表示有p位,则将Sk序列划分为如下几个区间,将每个区间的字符个数累加求和。
3. 计算是数字num的第几位(16进制),通过移位操作得到对应的字符即可。
C语言实现代码如下:
#include <stdio.h>
#include <assert.h>
//数n用16进制表示的位数
int hex_counts(int n)
{
int count = 0;
do {
count++;
n = n >> 4;
} while(n > 0);
return count;
}
//序列Sk中的数字个数
int sum(int k)
{
int i, p, sum;
p = hex_counts(k); //hexadecimal bits
sum = 0;
for (i = 1; i < p; i++) {
sum += ((1<<(4*i)) - (1<<(4*(i-1)))) * i;
}
sum += (k - (1<<(4*(p-1))) + 1) * p;
return sum;
}
//将数字n转化成十六进制
char upper(int n)
{
assert(n>=0 && n <= 15);
if (n >= 0 && n <= 9)
return '0' + n;
else
return 'A' + n - 10;
}
//返回Sk中第pos个字符
char get_value(int pos, int k)
{
int i, p, num, value, sum = 0;
p = hex_counts(k);
for (i = 1; i < p; i++) {
if (sum + ((1<<(4*i)) - (1<<(4*(i-1))))*i >= pos)
break;
sum += ((1<<(4*i)) - (1<<(4*(i-1))))*i;
}
num = (1<<(4*(i-1))) + (pos-sum-1)/i; //第pos个字符在数字num上,num共有i位
value = (num>>(4*(i - (pos-sum-1)%i - 1)))&0xF; //第pos个字符是num的第(pos-num-1)%i+1位
return upper(value);
}
//返回S1S2...Sk序列中的第i个字符
char get_pos(int i)
{
int k, tmp, count;
k = 1;
count = 0;
while (1) {
tmp = sum(k);
if (count + tmp >= i)
break;
count += tmp;
k++;
}
return get_value((i - count), k);
}
int main(void)
{
int i;
for (i = 1; i <= 200; i++) {
printf("%c", get_pos(i));
}
printf("\n");
return 0;
}
有个类似的题:POJ-1019 Number Sequence
这是一道关于十六进制序列的题目,给定一个位置i,需要找到第i个位置上的字符。例如,对于序列112123...,当i=50时,字符为5,i=100时,字符为9。解决方法包括确定i所在的序列,计算在序列中的位置,然后找出对应的16进制数字的哪一位。提供的C语言实现代码可帮助完成这一转换。
845

被折叠的 条评论
为什么被折叠?



