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