每日一题:求连续序列第n个数字

题目原型

要求:

在无限的整数序列 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, …中找到第 n 个数字。
注意:
n 是正数且在32为整形范围内 ( n < 2的31次方)。
输入:11
输出:0
说明:
第11个数字在序列 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, … 里是0,它是10的一部分。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/nth-digit
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

初级想法

  最简单的方法,一个数一个数的数。

每日一题:求连续序列第n个数字_第1张图片

int GetNNum(int n)
{
	int sum = 0;
	int i = 1;
	int tmp = 0;
	int j = 0;
	
	// 当前对输入的要求并不严格,输入过大,会导致数字越界,程序陷入死循环
	for (; i < 0x0fffffff; i = i*10; j++)
	{
		int flag = 1;
		int index = 0;
		// 获取序列中某个数中包含多少个数字
		while (i/flag >= 1)
		{
			flag *= 10;
			index++;
		}
		tmp  = sum;
		sum += index;
		if (sum >= n)
			break;
	}
	// 获取输出在目标数字中的第几位
	int n_num = n - tmp;
	char buf[256] = {0};
	sprintf(buf, "%d", i);
	return(buf[n_num - 1] - '0');
}

优化代码

本问题的关键在于寻找序列中的目标数字,有了大体思路就可以对代码进行优化,发现中间过程一个数一个数的去找目标数字的工作是没有必要的,可以定位目标数字所在区间在进行,用目标数字在区间内的相对位置与区间底数的和获取目标数字。前一版本虽然效率低下且问题巨大,但可以作为后续版本测试的模版,往往越笨的方法得出的结果越正确,只是效率有待提升。

int findNthDigit(int n) {
             long long sum = 0;
             long long i = 1;
             long long tmp = 0;
             double j = 1;
            
            //找到数字的范围区间
             for (; ; i = i*10, j++)
             {
                 tmp  = sum;
                 // 以求和的方式往往容易造成越界
                 sum += (long long)((pow(10, j) - pow(10, j-1)) * j);
                 if (sum >= (long long)n || (i * 10) == 0)
                     break;
             }
             
             //获取到目标数字
             int k = (n - tmp)/j;
             if ((long long)(n - tmp)%(long long)j != 0)
                k++;
             /*while(1)
             {   //舍弃运行超时方案,优化效率90%,已经达到精就已满足,不是自己想不到,是对自己的要求不够高
                 if (tmp + j * k >=n)
                     break;
                 k++;
             }*/
             // 获取输出在目标数字的相对位置
             int n_num = j - ((tmp + j*k) - n);
             char buf[256] = {0};
              
             // 将数字转字符串,以数组的形式获取输出
             sprintf(buf, "%d", i+k-1);
             printf("%d\n", buf[n_num - 1] - '0');
             return(buf[n_num - 1] - '0');
}

模版

 int findNthDigit(int n) {
        int i =1; 
		// 循环条件获取区间             
        while(n>i*(pow(10,i-1))*9)
        {
        	// 1- 9是i =1的区间,10-99是i=2的区间,以此类推
        	// 减去区间外的数字,以获取正确区间,所有变量都小于n,不会越界
            n-=i*(pow(10,i-1))*9;  
            i++;                   //标志位++;
        }
        // pow(10,i-1)区间基数,(n-1)/i区间相对位置
        int am_num=(n-1)/i+pow(10,i-1);  
        string a=to_string(am_num);     
        if(n%i==0)return (a[i-1]-'0');   
         return (a[n%i-1]-'0');     
    }

你可能感兴趣的:(c,和,c++每日一题)