问题:求序列a1,a2......an的最长递增子序列
- 复杂度为O(n2)的算法。
最优子结构分析,假设以ai为最后一个元素的最长递增子序列S,其长度为L,ak为最长递增子序列中满足k<i且ak<ai的k最大的一个,也就是在递增序列中ai的前一个元素,那么以ak为最后一个元素的最长递增子序列必定是S-ai,其长度为L-1。用反证法证明:假设存在以ak为最后一个元素的递增子序列的长度大于L-1,那么肯定存在长度大于L的以ai为最后一个元素的子序列S1,产生矛盾。
递归的定义最优解:假设L[i]表示以ai为最后一个元素的最长递增子序列的长度。L[i]=Max{L[k]+1, 1} 1=<k<i && ak<ai,有了这个递归式之后代码可以很简单的写出,代码如下:
1 //复杂度为n平方的算法
2 int LongestIncreaseSequen(int data[], unsigned int length)
3 {
4 int b[20];//就是上述说明中的L[i]
5 int c[20];//为了构造最优解,使用的数据结构
6 b[0] = 1;
7 for (int i=0; i<length; i++)
8 {
9 b[i]=1;
10 c[i]=-1;
11 for (int j=0; j<i; j++)
12 {
13 if (data[i]>data[j] && b[j]+1>b[i])
14 {
15 b[i] = b[j]+1;
16 c[i] = j;
17 }
18 }
19 }
20
21 //下面的代码是输出就有结果
22 int Max = 0;
23 int index = 0;
24 for (i=0; i<length; i++){
25 if (b[i]>Max)
26 {
27 Max = b[i];
28 index = i;
29 }
30 }
31 int temp = c[index];
32 cout << b[index] << endl;
33 cout << data[index] <<" ";
34 while (temp != -1)
35 {
36 cout << data[temp] << " ";
37 temp = c[temp];
38 }
39
40 return Max;
41 }
解法二:复杂度为nlg(n)的算法
《算法导论》上关于这个的提示,反正我是没看明白,不知道大家看明白了没有。这里说说我的理解,其实要把算法复杂度由n降到lg(n),我觉得应该首先要考虑下能不能使用二分法。这道题目就是应用的二分查找。一般来说要降低算法的复杂度,一个途径是增加空间消耗,还有一个途径就是利用更多的信息。其实《算法导论》上的提示应该是:长度为i的子序列的最后一个元素的最小值B[i]肯定大于长度为i-1的子序列的最后一个元素的最小值B[i-1]。回到问题本身如果a[j]大于当前B[]数组中的最大值那么说明原问题的递增子序列的长度Len可以加1,而且要更新数组B;当不大于的时候也要相应的更新B数组,这里的更新就用到了二分查找,比如说找到了a[j]大于B[k]且小于B[k+1]说明子序列长度为k+1的最后一个元素的最小值要更新为a[j]。B数组肯定是有序的。代码如下:
1 int BinSearch(int *B, int len,int w){
2 int left = 0;
3 int right = len-1;
4 int mid;
5 while (left<=right)
6 {
7 mid = (left+right)/2;
8 if (B[mid] == w)
9 {
10 return mid;
11 }
12 if (B[mid]<w)
13 {
14 left = mid + 1;
15 }else{
16 right = mid - 1;
17 }
18 }
19 return (B[mid] > w)?mid:mid+1;
20 }
21
22 //nlg(n)的算法
23 int LIS(int data[], unsigned int length)
24 {
25 int B[10]; //b[c]中存放的是当前长度为c的递增子序列的最后一个元素的最小值
26 B[0] = data[0];
27 int len = 1;
28 for(int i=1; i<length; i++)
29 {
30 if (data[i] > B[len-1])
31 {
32 B[len] = data[i];
33 len++;
34 }else
35 {
36 int pos = BinSearch(B, len, data[i]);
37 B[pos] = data[i];
38 }
39 }
40 return len;
41 }
浙公网安备 33010602011771号