編程之美2.16 最長上升子序列

來源:互聯網
上載者:User

 如何求一個一維數組(N個元素)中最長遞增子序列?
例如給定序列1-1,2,-3,4,-5,6,,-7,其中最長遞增子序列的長度為4(如1,2,4,6)。
經典解法:也是傳統解法,動態規劃,每加入一個新的數字,則檢查是否和前面所記錄的序列能組成更長序列。樣本如下:
掃描序列     1 -1 2 -3 4 ……
記錄序列最大值   1 -1 2  1 4 ……
記錄序列長度     1  1 2 -3 3 ……
代碼如下:

int LIS(int array[], int len){int List[MaxLen];int max = 0;for(int i = 0; i < len; i++){List[i] = 1;for(int j = 0; j < i; j++){if(array[i] > array[j] && List[j] + 1 > List[i]){List[i] = List[j] + 1;}}if(List[i] > max)max = List[i];}return max;}

改進解法:傳統解法的時間複雜度O(N^2)。顯然效率不高,也是較基本的一種解法,認真分析發現其中有大量重複判斷。舉個例子:
5 6 7 1 2 3 4 8.顯然當加入8的時候,只需和1 2 3 4構成序列即可,不必記錄和5 6 7構成序列的情況,這是關鍵,因為對於未來情況也就是8後面的情況,都是一樣的,所以完全不必記錄和5 6 7構成序列的情況。如果每加入一個數字,能夠按優先匹配曆史最長序列長度顯然能提高效率。
代碼如下:

int LIS(int array[], int len){int Maxs_Min_V[MaxLen];int nMaxLIS = 1;//初始最長遞增子序列的長度int List[MaxLen];Maxs_Min_V[1] = array[0];Maxs_Min_V[0] = -10000;//只要比數組中所有值小就行//初始化for(int k = 0; k < len; k++){List[k] = 1;}for(int i = 1; i < len; i++){//遍曆曆史最長遞增序列資訊int j = 0;for(j = nMaxLIS; j >= 0; j--){if(array[i] > Maxs_Min_V[j]){List[i] = j + 1;break;}}//如果當前最長序列大於最長遞增序列長度,更新最長資訊if(List[i] > nMaxLIS){nMaxLIS = List[i];Maxs_Min_V[nMaxLIS] = array[i];}else if(Maxs_Min_V[j] < array[i] && array[i] < Maxs_Min_V[j + 1]){Maxs_Min_V[j + 1] = array[i];}}return nMaxLIS;}

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.