LeetCode題解:longest-increasing-subsequence(最長遞增子序列)
阿新 • • 發佈:2018-12-05
題目描述
Example: Input: [10,9,2,5,3,7,101,18] Output: 4 Explanation: The longest increasing subsequence is [2,3,7,101], the length is 4. Note: There may be more than one result, it is only necessary for you to return the length. Your algorithm should run in O(n2) complexity. Follow up: Could you improve it to O(n log n) time complexity?
思路
這是一個經典的動態規劃演算法,假設v[i]代表最後節點為第i個節點的最長遞增子序列的長度,那麼更新的狀態方程為:
O(n²)級別的演算法一
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int * length = new int[nums.size()]();
int max = 0, result = 0;
for (int i = 0; i < nums.size(); i++) {
max = 0;
for (int j = 0; j < i; j++) {
if (nums[j] < nums[i]) {
max = max < length[j] ? length[j] : max;
}
}
max++;
length[i] = max;
result = result < max ? max : result;
}
delete [] length;
return result;
}
};
仍需努力仍需努力。
O(nlog(n))級別的演算法二
之前我們在更新時,不得不遍歷整個位於當前元素之前的元素來更新長度,有沒有更好的方法呢?
在此之前,我們需要先確認遞增序列的幾個性質:
- 如果有一個長度為m的遞增子序列A,當新的元素K加入時,要形成一條長為m+1的新序列,則K必須大於A的最後一個元素——記為last(A)。
- 如果有兩個長度均為m的遞增子序列A和B,那麼當K大於min(last(A), last(B))時,會獲得一條長為m+1的新序列。
- 令B[i] = k的含義為:長度為i的最短子序列的最小的最後一個值為k,那麼當i變大時,B[i]是嚴格遞增的。(這個在直觀上很好想象,當然通過反證法也是可以證明的)。
- 如果有c > a 且 c < b, 且B[m] = a, B[m+1] = b, 那麼B[m+1]=c。
所以,由上文的性質一和二,推出了性質三的資料結構的性質。而最後一個性質給出了這種結構的更新方法,以及嚴格遞增下二分法的實現可能。
程式碼如下:
class Solution {
public:
int bisearch(int start, int end, int* S, int key) {
if (S[end] < key) {
return end+1;
}
//針對(2,2)這種情況
if (S[end] == key) {
return end;
}
int mid = (start+end)/2;
if (S[mid] > key) {
if ( S[mid-1] < key) {
return mid;
}
return bisearch(start, mid-1, S, key);
}
return bisearch(mid+1, end, S, key);
}
int lengthOfLIS(vector<int>& nums) {
//針對[]
if (nums.empty()) {
return 0;
}
int * length = new int[nums.size()+1]();
int pos = 0, end = 1;
length[1] = nums[0];
//針對負數情況
length[0] = -10086;
for (int i = 1; i < nums.size(); i++) {
pos = bisearch(1, end, length, nums[i]);
end = end < pos ? pos:end;
length[pos] = nums[i];
}
delete [] length;
return end;
}
};
撒花兒~