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 |
} |