資料結構與演算法學習之路:LIS——最長遞增序列的動態規划算法和二分思想演算法_資料結構與演算法

來源:互聯網
上載者:User

一、最長遞增序列的問題描述:

求一個整數序列的最長遞增子序列,子序列不要求是連續的。例如:

Input:4,6,9,6,7,6,3,8,10;Output:5

二、解決方案:

1、用動態規劃的方法解決。從問題我們可以知道,我們最終得到的最長遞增子序列,其任意一段子序列也是對應序列中的最長子序列。這樣說可能不好理解,就以上面的例子來說:

最長子序列為:4,6, 7, 8, 10。在這段子序列的子序列裡選一個,例如:4,6,7。則4,6,7也是4,6,9,6,7,6,3這段序列的最長子序列。


對於動態規劃思想,我們最重要的是找到狀態和狀態轉移方程,那我們來看看這裡怎麼得到這兩個關鍵東西:


假設,nums={4,6,9,6,7,6,3,8,10},f(x)表示前x個數以nums[x]結尾的序列中,最長子序列的長度,那麼:


f(1)=1;f(2)=max{f(1)+1,1}=2;f(3)=max{f(2)+1,1},……以此類推。這裡或許有人問了,為什麼是f(x-1)+1和1比較啊。原因很簡單:以f(2)為例,f(2)=f(1+1),而f(1)=1,也就是說,f(2)的結果是和f(1)關聯的,而f(2)本身具有一個初始值1,根據問題要求f(2)的最終值應該是通過f(1)運算所得值和它的初始值選大的那一個。後面的也就以此類推了。


2、這種方法非常巧妙,主要思想是這樣的,我不管你的序列是由什麼組成的,我只在乎這個序列的長度是多少。於是我建立一個數組d[length],d[0]用來儲存最長序列長度,d[i]表示最長遞增序列長度為i時,序列的結尾元素。通過二分尋找不斷的為元素找插入的位置,構成一個最長序列。


這種解法的關鍵在於:我們要獲得的最長遞增序列,事實上只要保證每個位置的數字足夠小,而且有序,那麼得到的自然是最長子序列。說的可能不太清楚,大家可以通過代碼感受一下我的意思。


三、代碼:


1、O(n^2)的DP演算法


int lis1(int* nums, int length){int lis_len = 1;int d[9];for (int i = 0; i < length; ++i){d[i] = 1;for (int j = 0; j < i; ++j)if (nums[i] >= nums[j] && d[i] < d[j] + 1)++d[i];if (lis_len < d[i])lis_len = d[i];}return lis_len;}

2、O(nlogn)的二分思想演算法

int lis2(int* nums, int length){int d[9];int mid, left, right;d[0] = 1;d[1] = nums[0];for (int i = 1; i < length; ++i){left = 1;right = d[0];while (left <= right){mid = (left + right) / 2;if (nums[i] > d[mid])left = mid + 1;elseright = mid - 1;}d[left] = nums[i];if (left > d[0])++d[0];}return d[0];}


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.