最長上升子序列(實驗回顧)

今天的算法實驗課是關於最長上升子序列的,總結一下。ios

概念

首先須要知道,子串和子序列的概念,咱們以字符子串和字符子序列爲例,更爲形象,也能順帶着理解字符的子串和子序列:算法

  1. 字符子串指的是字符串中連續的n個字符,如abcdefg中,ab,cde,fg等都屬於它的字串。
  2. 字符子序列指的是字符串中不必定連續但前後順序一致的n個字符,便可以去掉字符串中的部分字符,但不可改變其先後順序。如abcdefg中,acdg,bdf屬於它的子序列,而bac,dbfg則不是,由於它們與字符串的字符順序不一致。

知道了這個,數值的子序列就很好明白了,即用數組成的子序列。這樣的話,最長上升子序列也很容易明白了,歸根結底仍是子序列,而後子序列中,按照上升順序排列的最長的就是咱們最長上升子序列了。數組

最長上升子序列(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

image-20201208225438176

相關文章
相關標籤/搜索