标签:
今天讲了最长非减子序列的长度的两种不同的时间复杂度的算法。yi
对于长度为N的数组A[N] = {a0, a1, a2, …, an-1},假设假设我们想求以aj结尾的最大递增子序列长度,设为L[j],
L[n] = 1;那么L[j] = max(L[i]) + 1, where i < j && a[i] < a[j],
也就是i的范围是i到n。这样,想求aj结尾的最大递增子序列的长度,
我们就需要遍历j之前的所有位置i(0到j-1),找出a[i] < a[j],计算这些i中,能产生最大L[i]的i,之后就可以求出L[j]。
之后我对每一个A[N]中的元素都计算以他们各自结尾的最大递增子序列的长度,
这些长度的最大值,就是我们要求的问题——数组A的最大递增子序列。
1 LIS 最长递增子序列 O(n^2) 2 #include <iostream> 3 #include <stdio.h> 4 #include <stdlib.h> 5 using namespace std; 6 7 void logest_increase_sub( const int* a, int ssize){ 8 int *d = new int[ssize](); 9 int *p = new int[ssize](); 10 d[ssize-1] = 1;//数组第一个元素的最大递增序列为1 11 for(int i = ssize-1; i >= 0; i--){ 12 int maxx = 0, index = 0; 13 for(int j = i; j < ssize; j++){ 14 if((a[i] < a[j]) && (maxx < d[j])){ 15 maxx = d[j]; 16 index = j; //记录下标 17 cout<<index<<" index "<<endl; 18 } 19 } 20 if(maxx == 0){ 21 d[i] = 1; 22 p[i] = -1; 23 }else{ 24 d[i] = maxx + 1; 25 p[i] = index; //记录索引 26 } 27 } 28 //寻找最长子序列的最大下标 29 int max_num = 0, max_index = 0; 30 for(int i = 0; i < ssize; i++){ 31 if(max_num < d[i]){ 32 max_num = d[i]; 33 max_index = i; 34 } 35 } 36 //输出 37 printf("\n最长子序列长度为: %d \n",max_num); 38 for(int i = max_index; i != -1; i = p[i]){ 39 cout << a[i]<<" "<<endl; 40 } 41 delete[]d; 42 delete[]p; 43 } 44 45 int main(){ 46 int ss[] = {10,22,9,33,21,50,41,60,80}; 47 logest_increase_sub(ss, 9); 48 return 0; 49 }
下面是时间复杂度为O(nlogn)的算法
我们定义一个序列B,然后逐个考察这个序列。
此外,我们用一个变量Len来记录现在最长算到多少了
首先,把d[1]有序地放到B里,令B[1] = 2。这时Len=1。
然后,把d[2]有序地放到B里,令B[1] = 1。这时Len=1。
d[3] = 5,d[3]>B[1]。这时候B[1..2] = 1, 5,Len=2
d[4] = 3,这时候B[1..2] = 1, 3,Len = 2
d[5] = 6, 这时B[1..3] = 1, 3, 6,还是很容易理解吧? Len = 3 了噢。
d[6] = 4,得到B[3] = 4。B[1..3] = 1, 3, 4, Len=3。
d[7] = 8,得到B[4]=8,B[1...4]=1,3,4,8Len变成4了
[8] = 9,B[5] = 9,嗯。Len=5了。
d[9] = 7,B[4] =7,B[1..5] = 1, 3, 4, 7, 9,Len = 5。
于是我们知道了LIS的长度为5。
1 #include <iostream> 2 #include <string.h> 3 #include <stdio.h> 4 5 using namespace std; 6 int ceilIndex(int A[], int left, int right, int value) 7 { 8 while (right -left > 1) 9 { 10 int mid = left + (right - left)/2; 11 if (A[mid] >= value) 12 right = mid; 13 else 14 left = mid; 15 } 16 return right; 17 } 18 19 int longestIncreasingSub(int A[], int size) 20 { 21 int *tailTable = new int[size]; 22 int len; // always points empty slot 23 memset(tailTable, 0, sizeof(tailTable[0])*size); 24 tailTable[0] = A[0]; 25 len = 1; 26 for (int i = 1; i < size; i++) 27 { 28 if (A[i] < tailTable[0]) 29 { 30 tailTable[0] = A[i];// new smallest value 31 }else if (A[i] > tailTable[len-1]) 32 { 33 // A[i] wants to extend largest subsequence 34 tailTable[len++] = A[i]; 35 }else{ 36 // 使用二分法查找 37 tailTable[ceilIndex(tailTable, -1, len-1, A[i])] = A[i]; 38 } 39 } 40 delete[] tailTable; 41 return len; 42 } 43 44 int main() 45 { 46 int A[] = { 2, 5, 3, 7, 11, 8, 10, 13, 6 }; 47 int n = ARRAY_SIZE(A); 48 printf("Length of Longest Increasing Subsequence is %d\n", 49 longestIncreasingSub(A, n)); 50 return 0; 51 }
标签:
原文地址:http://www.cnblogs.com/runhang/p/5014116.html