01 |
/*
求解最长递增子序列长度 */ |
02 |
#include
<iostream> |
03 |
#include
<limits> |
04 |
05 |
using namespace std; |
06 |
07 |
//int
x[] = {1,-1,2,-3,4,-5,6,-7}; |
08 |
int x[]
= {2, 1, 5, 3, 6, 4, 8, 9, 7}; |
09 |
int disp_array(int a[], int len); |
10 |
int find_first_bigger(int a[], int last, int key); |
11 |
12 |
int main() |
13 |
{ |
14 |
int len
= sizeof(x)/sizeof(x[0]); |
15 |
int *z
= new int(len
+ 1); |
16 |
/*
z[i] = min(t|t:长度为i的子序列的最后一个元素) */ |
17 |
z[0]
= std::numeric_limits<int>::min(); |
18 |
for (int i
= 1; i <= len; ++i) |
19 |
{ |
20 |
z[i]
= 0; |
21 |
} |
22 |
23 |
disp_array(x,
len); |
24 |
disp_array(z,
len + 1); |
25 |
26 |
int t,
lislen = 0; |
27 |
for (int i
= 0; i < len; ++i) |
28 |
{ |
29 |
t
= find_first_bigger(z, lislen, x[i]); |
30 |
if (t
> lislen) |
31 |
z[++lislen]
= x[i]; /*
z[]中没有比x[i]大的*/ |
32 |
else |
33 |
z[t]
= x[i]; /*
z[t]第一个比x[i] */ |
34 |
35 |
} |
36 |
37 |
disp_array(z,
len + 1); |
38 |
cout
<< "LIS
= " <<
lislen << endl; |
39 |
|
40 |
return 0; |
41 |
} |
42 |
43 |
/** |
44 |
*
@brief 在数组a[0..last]中,自左向又查找第一个比key大的数的下标 |
45 |
*
时间复杂度O(lg(n)) |
46 |
* |
47 |
*
@param a[] |
48 |
*
@param last |
49 |
*
@param key |
50 |
* |
51 |
*
@return 返回下标,如果没有比key大的则返回last+1 |
52 |
*/ |
53 |
int find_first_bigger(int a[], int last, int key) |
54 |
{ |
55 |
int m,
p = -1, q = last + 1; |
56 |
/*
assume: a[-1] < key <= a[last + 1] */ |
57 |
while (p
+ 1 != q) |
58 |
{ |
59 |
/*
invartant: 0 <= p + 1 < q <= last + 1 && a[p] < key <= a[q]*/ |
60 |
m
= p + ((q - p)>>1); |
61 |
if (a[m]
< key) |
62 |
p
= m; |
63 |
else |
64 |
q
= m; |
65 |
} |
66 |
67 |
return q; |
68 |
} |
69 |
70 |
int disp_array(int a[], int len) |
71 |
{ |
72 |
for (int i
= 0; i < len; ++i) |
73 |
{ |
74 |
cout
<< a[i]; |
75 |
if (i
== len -1) |
76 |
cout
<< endl; |
77 |
else |
78 |
cout
<< "
"; |
79 |
} |
80 |
|
81 |
} |
本文介绍了一种求解最长递增子序列长度的高效算法,并通过C++代码实现。该算法利用动态规划思想,结合二分查找技巧,有效地解决了最长递增子序列问题。
1788

被折叠的 条评论
为什么被折叠?



