算法題19 把數組排成最小的數


題目

  輸入一個正整數數組,將他們連接起來排成一個數,輸出所有排出的數字中最小的一個。例如:輸入數組[32,321],輸出所能排出的最小數為:32132.請給出該問題的算法。

分析

  對於元素位置排列的問題,如a,b,我們希望找到一種排列規則,來確定我們所要得到的是a,b還是b,a. 題目要求得到所能排出的最小的數,那如a<b,則從常識來看ab<ba。這個比較規則到底正不正確呢?在劍指offer一書中有很好的證明

  http://zhedahht.blog.163.com/blog/static/25411174200952174133707/

  一個有效的比較規則需要三個條件:自反性、對稱性、傳遞性。證明過程如下

  1. 自反性。即a=a.

   顯然如aa=aa,則a=a

  2. 對稱性。即如果a>b,則b<a.

   如果a<b,由規則ab<ba,顯然ba>ab,即b>a.

  3. 傳遞性。即如果a<b,b<c,則a<c

   假設有條件a<b,b<c,則根據規則ab<ba,bc<cb. 假設a,b,c在高位時的10冪數分別為m,n,l

   則a*10^m+b<b*10^n+a —》a*(10^m-1)<b*(10^n-1);

    b*10^n+c<c*10^l+b —》b*(10^n-1)<c*(10^l-1);

   因此有a*(10^m-1)<c*(10^l-1)

     即a*10^m+c<c*10^l+a —》ac<ca

   所以有a<c

我們也可以用分情況討論的思路證明這個規則。對於數組中的a,b來說,排出的數字要么a在b前面,要么b在a前面。假設其他元素已經排成一個最小值XXX。有以下三種情況

http://blog.csdn.net/wuzhekai1985/article/details/6704902

  1. abXXX

   顯然如果ab<ba,abXXX<baXXX

  2. XXXab

   顯然如果ab<ba,abXXX<baXXX

  3. aXXXb

   我們將中間部分看成c,則有acb.我們已知ab<ba,需證明acb<bca。假設a,c,b的位數分別是m,n,l

   若acb>bca,則a*10^m+c*10^n+b>b*10^l+c*10^n+a ,兩邊同時減c*10^n —》a*10^m+b>b*10^l+a 即ab>ba和已知矛盾。由此可證acb<bca

代碼

 1  const int max_digits=10;
 2  int catstr_max_len=2*max_digits+1;
 3  char* catstr1=new char[catstr_max_len];
 4  char* catstr2=new char[catstr_max_len];
 5  int comp(const void* a,const void* b)
 6  {
 7      sprintf(catstr1,"%d%d",*(int*)a,*(int*)b);
 8 
 9      sprintf(catstr2,"%d%d",*(int*)b,*(int*)a);
10 
11      return strcmp(catstr1,catstr2);
12  }
13  void PrintMinNumber(int numbers[],int len)
14  {
15      if (!numbers||len<=0)
16      {
17          throw std::exception("Invalid input.");
18      }
19 
20      //char* strnum=new char[len*max_digits];
21      qsort(numbers,len,sizeof(int*),comp);
22 
23      for (int i=0;i<len;i++)
24      {
25          cout<<numbers[i];
26      }
27      cout<<endl;
28  }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM