码迷,mamicode.com
首页 > 其他好文 > 详细

非递减子序列的最大长度

时间:2015-12-02 22:19:38      阅读:206      评论:0      收藏:0      [点我收藏+]

标签:

今天讲了最长非减子序列的长度的两种不同的时间复杂度的算法。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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!