資料結構與演算法(二十)

2021-08-20 08:50:53 字數 3813 閱讀 8117

數字以012345678910111213141516171819…的格式序列化到乙個字串行中。在這個序列中,第5位(從0開始計數)是5,第13位是1,第19位是4,等等。請寫乙個函式,求任意第n位對應的數字。

1、舉例子,找規律。比如現在要找第1001位的數字是什麼?

2、序列的前10位是個位數0~9都是只有一位的數字。顯然第1001位在這10個數字之後,因此這10個數字可以直接跳過。我們再從後面緊跟著的序列中找第991(1001-10)位數字

3、接下來的180位數字是10~99共90個2位數。由於

991>

180(=90

∗2) 991

>

180(=90

∗2

),所以第991位在所有的兩位數之後,我們再跳過90個兩位數,繼續從後面找811(=991-180)位

4、接下來的2700位數字是100~999共900位3位數。由於

811<

2700(=

900∗3)

811<

2700(=

900∗3)

,所以第811位是某個三位數中的乙個。由於

811=

270∗3+

1 811

=270∗3

+1

,所以第811位是從100開始的第270個數字即370的第1位,即7(第0位是3)

int digitatindex(int

index)

}//計算m位長的數字一共由多少個,比如傳入2,輸出90

int countofintegers(int digits)

//對核心函式進行過載

//當我們知道要找的那一位數字位於某m位數之後,使用該函式找出要找的那個數

int digitatindex(int

index, int digits)

//m位長的數的第乙個是啥,比如2位是100,3位是1000

int beginnumber(int digits)

輸入乙個正整數陣列,把陣列裡所有陣列拼接起來排成乙個數,列印能拼接出的所有數字中的最小的乙個,例如,輸入陣列,則列印出這3個數字能排成的最小數字321323

1、這道題其實是希望我們找到乙個排序規則,陣列根據這個規則排序之後能排成乙個最小的數字。要確定排序規則,就要比較這兩個數字,也就是給出兩個數字m和n,我們需要確定乙個規則判斷m和n哪個應該排在前面,而不是僅僅比較這兩個數字的值哪個更大

2、根據題目的要求,兩個數字m和n能拼接成數字mn和nm。如果mn

m

n

,那麼我們應該列印出mn,也就是說m應該排在n的前面,我們定義此時的m小於n;反之,若nm

n

m

,則定義n小於m;若mn

=nm mn=

nm

,則m等於n。在下文中,符號「<、>、=」表示常規意義的數值的大小關係,而文字「大於、小於、等於」表示新定義的大小關係

3、接下來考慮怎麼拼接數字,即給出數字m和n,怎麼得到數字mn和nm並比較它們的大小。直接用數值去計算很簡單,但需要考慮到乙個潛在問題就是m和n都在int型能表達的範圍內,但把它們拼接起來的數字mn和nm用int型表示就有可能溢位了,所以這是乙個**的大數問題

4、大數問題,就想到字串。另外,由於把數字m和n拼接起來得到mn和nm,它們的位數肯定是相同的,因此比較它們的大小只需按照字串大小的比驕傲規則就可以了。

//int型變數的最長位數

const

int g_maxnumberlength = 10;

//後面還要加1?因為變為字串後面多了乙個字串結束標誌「\0」

char* strcombine_1 = new

char[g_maxnumberlength * 2 + 1];

char* strcombine_2 = new

char[g_maxnumberlength * 2 + 1];

void printminnumber(int* numbers, int length)

//②對字串陣列strnumbers進行排序,對陣列中所有的字串進行排序

qsort(strnumbers, length, sizeof(char*), compare);

//③輸出已經排好序的字串陣列char**

for (int i = 0; i < length; i++)

cout

<< strnumbers[i];

cout

<< endl;

//④要注意把請求的記憶體空間給釋放了delete

for (int i = 0; i < length; i++)

delete strnumbers[i];

delete strnumbers;

}// 如果[strnumber1][strnumber2] > [strnumber2][strnumber1], 返回值大於0

// 如果[strnumber1][strnumber2] = [strnumber2][strnumber1], 返回值等於0

// 如果[strnumber1][strnumber2] < [strnumber2][strnumber1], 返回值小於0

int compare(const

void* strnumber1, const

void* strnumber2)

這道題有乙個容易被忽視的點就是大數問題!!

給定乙個數字,我們按照如下規則把它翻譯為字串:0翻譯成「a」,1翻譯成「b」,……,11翻譯成「l」,……,25翻譯成「z」。乙個數字可能有多種翻譯。例如,12258有5種不同的翻譯,分別是「bccfi」、「bwfi」、「bczi」、「mcfi」和「mzi」。請實現乙個函式,用來計算乙個數字有多少種不同的翻譯方法

1、有兩種不同的選擇來翻譯第乙個數字1.第一種是數字1單獨翻譯成「b」,後面剩下數字2558;第二種是1和緊挨著的2組成12翻譯成「m」,後面剩下數字258

2、當最開始的乙個或兩個數字被翻譯成乙個字元後,我們接著翻譯後面剩下的數字。這很明顯又是乙個遞迴的問題。

3、定義函式f(

i)f (i

)表示從第i個數字開始的不同翻譯的數目,那麼f(

i)=f

(i+1

)+g(

i,i+

1)∗f

(i+2

) f(i

)=f(

i+1)

+g(i

,i+1

)∗f(

i+2)

。當第i位和第i+1位兩位數字拼接起來的數字在10~25的範圍內,函式g(

i,i+

1)g (i

,i+1

)的值為1;否則為0

4、由於存在重複的子問題,遞迴並不是解決這個問題的最佳方法。還是以12258為例。如前所屬,翻譯12258可以分解成兩個子問題:翻譯1和2558。接下來我們翻譯第乙個子問題中剩下的2558,同樣也可以分解成兩個子問題:翻譯2和258,以及翻譯22和58.注意到子問題翻譯258重複出現了

5、遞迴從最大的問題開始自上而下解決問題。我們也可以從最小的子問題開始自下而上解決問題,這樣就可以消除重複的子問題。也就是說,我們從數字的末尾開始,然後從右到左翻譯並計算不同翻譯的數目。

int gettranslationcount(int number)

//過載,引數是字串

int gettranslationcount(const string& number)}}

}

資料結構與演算法(二十四)

給定乙個陣列和滑動視窗的大小,請找出所有滑動視窗裡的最大值。例如,如果輸入陣列及滑動視窗的大小3,那麼一共存在6個滑動視窗,它們的最大值分別為 1 乙個滑動視窗可以看成乙個佇列。當視窗滑動時,處於視窗的第乙個數字被刪除,同時在視窗的末尾新增乙個新的數字。這符合佇列 先進先出 特性。2 題意 陣列中的...

資料結構與演算法(二十一)

插入排序回顧 插入排序演算法 definsertsort alist for index in range 1 len alist currentvalue alist index position index while position 0and alist position 1 current...

資料結構與演算法 演算法 演算法和資料結構

資料結構與演算法 演算法 好吧,在這裡,您被優秀或優秀的軟體開發人員所隔開。在這種情況下,我會告訴您一開始或至少在我的情況下,並且我知道大多數時候,對於我認識的大多數人,您會覺得自己是乙個無能的人或白痴。基本上,我怎麼可能不理解這一點,然後您會感到沮喪。在這種情況下,我會告訴您情況並不像您想的那麼糟...