日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

程序员面试题精选100题(41)-把数组排成最小的数[算法]

發布時間:2025/3/21 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 程序员面试题精选100题(41)-把数组排成最小的数[算法] 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目:輸入一個正整數數組,將它們連接起來排成一個數,輸出能排出的所有數字中最小的一個。例如輸入數組{32,??321},則輸出這兩個能排成的最小數字32132。請給出解決問題的算法,并證明該算法。

分析:這是096月份百度新鮮出爐的一道面試題,從這道題我們可以看出百度對應聘者在算法方面有很高的要求。

這道題其實是希望我們能找到一個排序規則,根據這個規則排出來的數組能排成一個最小的數字。要確定排序規則,就得比較兩個數字,也就是給出兩個數字mn,我們需要確定一個規則mn哪個更大,而不是僅僅只是比較這兩個數字的數值哪個更大。

根據題目的要求,兩個數字mn排成的數字mnnm,如果mn<nm,那么我們應該輸出mn,也就是m應該排在n的前面,也就是m小于n;反之,如果nm<mnn小于m。如果mn==mnm等于n

接下來我們考慮怎么去拼接數字,即給出數字mn,怎么得到數字mnnm并比較它們的大小。直接用數值去計算不難辦到,但需要考慮到的一個潛在問題是mn都在int能表達的范圍內,但把它們拼起來的數字mnnm就不一定能用int表示了。所以我們需要解決大數問題。一個非常直觀的方法就是把數字轉換成字符串。

另外,由于把數字mn拼接起來得到的mnnm,它們所含有的數字的個數肯定是相同的。因此比較它們的大小只需要按照字符串大小的比較規則就可以了。

基于這個思路,我們可以寫出下面的代碼:

// Maxinum int number has 10 digits in decimal system const int g_MaxNumberLength = 10;// String buffers to combine two numbers char* g_StrCombine1 = new char[g_MaxNumberLength * 2 + 1]; char* g_StrCombine2 = new char[g_MaxNumberLength * 2 + 1];// Given an array, print the minimum number // by combining all numbers in the array void PrintMinNumber(int* numbers, int length) {if(numbers == NULL || length <= 0)return;// Convert all numbers as stringschar** strNumbers = (char**)(new int[length]);for(int i = 0; i < length; ++i){strNumbers[i] = new char[g_MaxNumberLength + 1];sprintf(strNumbers[i], "%d", numbers[i]);}// Sort all strings according to algorithm in function compareqsort(strNumbers, length, sizeof(char*), compare);for(int i = 0; i < length; ++i)printf("%s", strNumbers[i]);printf("\n");for(int i = 0; i < length; ++i)delete[] strNumbers[i];delete[] strNumbers; }// Compare two numbers in strNumber1 and strNumber2 // if [strNumber1][strNumber2] > [strNumber2][strNumber1], // return value > 0 // if [strNumber1][strNumber2] = [strNumber2][strNumber1], // return value = 0 // if [strNumber1][strNumber2] < [strNumber2][strNumber1], // return value < 0 int compare(const void* strNumber1, const void* strNumber2) {// [strNumber1][strNumber2]strcpy(g_StrCombine1, *(const char**)strNumber1);strcat(g_StrCombine1, *(const char**)strNumber2);// [strNumber2][strNumber1]strcpy(g_StrCombine2, *(const char**)strNumber2);strcat(g_StrCombine2, *(const char**)strNumber1);return strcmp(g_StrCombine1, g_StrCombine2); }

上述代碼中,我們在函數compare中定義比較規則,并根據該規則用庫函數qsort排序。最后把排好序的數組輸出,就得到了根據數組排成的最小的數字。

找到一個算法解決這個問題,不是一件容易的事情。但更困難的是我們需要證明這個算法是正確的。接下來我們來試著證明。

首先我們需要證明之前定義的比較兩個數字大小的規則是有效的。一個有效的比較需要三個條件:1.自反性,即a等于a2.對稱性,即如果a大于b,則b小于a3.傳遞性,即如果a小于bb小于c,則a小于c。現在分別予以證明。

1.??????

自反性。顯然有 aa=aa,所以 a=a

2.???????對稱性。如果a小于b,則ab<ba,所以ba>ab。因此b大于a

3.???????傳遞性。如果a小于b,則ab<ba。當ab用十進制表示的時候分別為l位和m位時,ab=a×10m+bba=b×10l+a。所以a×10m+b<b×10l+a。于是有a×10m-a< b×10l?–b,即a(10m?-1)<b(10l?-1)。所以a/(10l?-1)<b/(10m?-1)

如果b小于c,則bc<cb。當c表示成十進制時為m位。和前面證明過程一樣,可以得到b/(10m?-1)<c/(10n?-1)

所以a/(10l?-1)< c/(10n?-1)。于是a(10n?-1)<c(10l?-1),所以a×10n?+c<c×10l?+a,即ac<ca

所以a小于c

在證明了我們排序規則的有效性之后,我們接著證明算法的正確性。我們用反證法來證明。

我們把n個數按照前面的排序規則排好順序之后,表示為A1A2A3…An。我們假設這樣排出來的兩個數并不是最小的。即至少存在兩個xy0<x<y<n),交換第x個數和地y個數后,A1A2…Ay…Ax…An<A1A2…Ax…Ay…An

由于A1A2…Ax…Ay…An是按照前面的規則排好的序列,所以有Ax<Ax+1<Ax+2<…<Ay-2<Ay-1<Ay

由于Ay-1小于Ay,所以Ay-1Ay<AyAy-1。我們在序列A1A2…Ax…Ay-1Ay…An交換Ay-1Ay,有A1A2…Ax…Ay-1Ay…An<A1A2…Ax…AyAy-1…An(這個實際上也需要證明。感興趣的讀者可以自己試著證明)。我們就這樣一直把Ay和前面的數字交換,直到和Ax交換為止。于是就有A1A2…Ax…Ay-1Ay…An<A1A2…Ax…AyAy-1…An< A1A2…Ax…AyAy-2Ay-1…An<…< A1A2…AyAx…Ay-2Ay-1…An

同理由于Ax小于Ax+1,所以AxAx+1<Ax+1Ax。我們在序列A1A2…AyAxAx+1…Ay-2Ay-1…An僅僅只交換AxAx+1,有A1A2…AyAxAx+1…Ay-2Ay-1…An<A1A2…AyAx+1Ax…Ay-2Ay-1…An。我們接下來一直拿Ax和它后面的數字交換,直到和Ay-1交換為止。于是就有A1A2…AyAxAx+1…Ay-2Ay-1…An<A1A2…AyAx+1Ax…Ay-2Ay-1…An<…< A1A2…AyAx+1Ax+2…Ay-2Ay-1Ax…An

所以A1A2…Ax…Ay…An< A1A2…Ay…Ax…An。這和我們的假設的A1A2…Ay…Ax…An?<A1A2…Ax…Ay…An相矛盾。

所以假設不成立,我們的算法是正確的。

?

本文已經收錄到《劍指Offer——名企面試官精講典型編程題》一書中,有改動,書中的分析講解更加詳細。歡迎關注。

本題已被九度Online Judge系統收錄,歡迎讀者移步到http://ac.jobdu.com/hhtproblems.php在線測試自己的代碼。

博主何海濤對本博客文章享有版權。網絡轉載請注明出處http://zhedahht.blog.163.com/。整理出版物請和作者聯系。

總結

以上是生活随笔為你收集整理的程序员面试题精选100题(41)-把数组排成最小的数[算法]的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。