代碼來源於:http://hi.baidu.com/daoyuanlee/blog/item/f5ccff07e58f69cf7a89473b.html
O(n^2) 演算法的思想
基於動態規劃:用數組a記錄數字序列,數組b記錄各a各個首碼子序列的最長嚴格遞增子序列的長度(即b[i]記錄的是a[0]...a[i]的最長嚴格遞增子序列的長度)
顯然有b[0]=1,即a[0]的最長嚴格遞增子序列長度顯然為1
在這個情況下進行增長,a[1]如果比a[0]大,那麼b[1]就為b[0]+1=2. 否則b[1]仍然為1(即最長嚴格遞增子序列為a[0]或a[1])
繼續增長至a[0],a[1],...a[i-1]的情況,此時b中下標0至i的部分也儲存了長度由1至i-2的a的首碼子序列的最長嚴格遞增子序列的長度。
此時我們從0至i-1迭代,並維護一個max變數:
1 int max = 0;
2 for (j = 0; j < i; j ++)
3 if (max < b[j] && a[j] < a[i]) max = b[j];
4 b[i] = max + 1;
迭代過程中維護一變數max,迭代中,當滿足以下2條件時更新max:
1. max < b[j]
2. a[j] < a[i]
使得max取到的是b[0]...b[i-1]中的最大值(假設為b[x]),即a[0]...a[i-1]的最長嚴格遞增子序列的長度;且有a[x]<a[i],即下一個增長到尾部的元素可以為增加當前最長嚴格遞增子序列的長度。
因此a[0]...a[i]的最長嚴格遞增子序列的長度為max+1.
增長持續至整個序列都被加入後,只需要遍曆b,取出其中最大的值,即為a的最長嚴格遞增子序列的長度。
O(n*logn)演算法
#include <iostream>
using namespace std;
const int MAX = 100;
int b[MAX];
int bs(int x,int k)
{
if(x < b[1]) return 1;
int left = 1, right = k, mid;
while(left < right-1)
{
mid = (left+right)/2;
if(b[mid] <= x) left = mid;
else right = mid;
}
return right;
}
int LIS(int n, int a[])
{
int k = 1;
b[1] = a[0];
for(int i = 1; i < n; ++i)
{
if(a[i] > b[k]) b[++k] = a[i];
else if(a[i] != b[k]) b[bs(a[i], k)] = a[i];
}
return k;
}
int main()
{
int n, i, a[MAX];
while(scanf("%d", &n) == 1)
{
for(i = 0; i < n; ++i) scanf("%d", &a[i]);
printf("%d\n", LIS(n, a));
}
return 0;
}