今天的算法實驗課是關於最長上升子序列的,總結一下。ios
首先須要知道,子串和子序列的概念,咱們以字符子串和字符子序列爲例,更爲形象,也能順帶着理解字符的子串和子序列:算法
知道了這個,數值的子序列就很好明白了,即用數組成的子序列。這樣的話,最長上升子序列也很容易明白了,歸根結底仍是子序列,而後子序列中,按照上升順序排列的最長的就是咱們最長上升子序列了。數組
最長上升子序列(Longest Increasing Subsequence),簡稱LIS,也有些狀況求的是最長非降序子序列,兩者區別就是序列中是否能夠有相等的數。假設咱們有一個序列bi,當b1 < b2 < … < bS的時候,咱們稱這個序列是上升的。對於給定的一個序列(a1, a2, …, aN),咱們也能夠從中獲得一些上升的子序列(ai1, ai2, …, aiK),這裏1<=i1<i2<…<iK<=N,但必須按照從前到後的順序。好比,對於序列(1, 7, 3, 5, 9, 4, 8),咱們就會獲得一些上升的子序列,如(1,7,9), (3,4,8), (1,3,5,8)等等,而這些子序列中最長的(如子序列(1,3,5,8)),它的長度爲4,所以該序列的最長上升子序列長度爲4。spa
還有一個很是重要的問題:請你們用集合的觀點來理解這些概念,子序列、公共子序列以及最長公共子序列都不惟一,但很顯然,對於固定的數組,雖然LIS序列不必定惟一,但LIS的長度是惟一的。再拿咱們剛剛舉的栗子來說,給出序列 ( 1, 7, 3, 5, 9, 4, 8),易得最長上升子序列長度爲4,這是肯定的,但序列能夠爲 ( 1, 3, 5, 8 ), 也能夠爲 ( 1, 3, 5, 9 )。code
輸入: 2 3 6 1 7 4 10 8 9ci
設maxlength[i]存儲以第i個元素結束的子問題最長上升子序列的長度字符串
子問題(數組的每一位遍歷) | maxlength 元素值 |
---|---|
子問題:2 | maxlength[1]=1 初值 |
子問題:2 3 | maxlength[2]= maxlength[1]+1 |
子問題:2 3 6 | maxlength[3]= maxlength[2]+1 |
子問題:2 3 6 1 | maxlength[4]= 1 |
子問題:2 3 6 1 7 | maxlength[5]= maxlength[3]+1 |
子問題:2 3 6 1 7 4 | maxlength[6]= maxlength[2]+1 |
子問題:2 3 6 1 7 4 10 | maxlength[7]= maxlength[5]+1 |
子問題:2 3 6 1 7 4 10 8 | maxlength[8]= maxlength[5]+1 |
子問題:2 3 6 1 7 4 10 8 9 | maxlength[9]= maxlength[8]+1 |
#include <iostream> using namespace std; void LISLength(int a[], int n) { int *maxlength = new int[n]; // 定義一個存儲到每一位元素爲止的最長子序列長度的動態數組 *(maxlength+0) = 1; // 設置第一個元素的值爲1,及最小時爲1 int max = 1; // 保存最大最長子序列長度,初始化爲1,及最小爲1 // 遍歷每一位元素,保存到每一位元素前的最長子序列長度 for (int i = 1; i < n; i++) { int max_t = 0; // 初始化每一次的最長子序列長度 // 當前元素與以前元素的比較 for (int j = 0; j < i; j++) { // 當遍歷元素大於其前面的此元素,且大於遍歷過的最長子序列長度時 if (a[i] > a[j] && *(maxlength+j) > max_t) { max_t = *(maxlength + j); // 更新最長子序列長度 *(maxlength + i) = *(maxlength + j) + 1; // 到該遍歷元素的最長子序列長度 } // 當遍歷元素小於前面全部的元素時,設置到該遍歷元素的最長子序列長度 爲 1 else if(max_t == 0 && j == i -1) { *(maxlength + i) = 1; } } // 更新最長子序列長度值 if (*(maxlength + i) > max) max = *(maxlength + i); } cout << "最長子序列長度:" << max << endl; delete[] maxlength; // 銷燬動態數組 } int main() { int n = 0; cout << "請輸入數組大小:" << endl; cin >> n; int* arr = new int[n]; // 定義動態數組 cout << "請輸入數據:" << endl; // 輸入數組數據 for (int i = 0; i < n; i++) { cin >> *(arr+i); } LISLength(arr, n); delete[] arr; // 銷燬動態數組 return 0; }
效果io