每日一題:求連續序列第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
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。

初級想法

  最簡單的方法,一個數一個數的數。

暴力操作

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');     
    }

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章