-
Notifications
You must be signed in to change notification settings - Fork 77
/
lis.cpp
157 lines (144 loc) · 3.94 KB
/
lis.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#define MAX 100
int dp[MAX];
//int x[] = {-7, 10, 9, 2, 3, 8, 8, 1};
//int x[] = {389, 207, 155, 300, 299, 170, 158, 65};
int x[] = {1, 2, 3, 4, 5, 4, 3, 2, 1, 10};
int N = (sizeof x / sizeof(int)) - 1;
void _reset() {
memset(dp, -1, sizeof dp);
}
/**
Index value of longest increasing subsequence in O(n^2) - Recursively with dp apporoach.
Ultimately this recursive approach is not better than iterative as
all sub problems are revisited.
**/
int LIS(int i) {
if(i == 0) return 1;
if (dp[i] != -1) {
return dp[i];
}
int ans = 1;
for(int j = 0; j < i; j++) {
if (x[i] > x[j]) {
ans = max(ans, 1 + LIS(j));
}
}
return dp[i] = ans;
}
/**
Longest Increasing Subsequence Length of full array in O(n^2) - Iteratively with dp apporoach.
**/
int pos;
int LIS() {
_reset();
dp[0] = 1;
for(int i = 1; i <= N; i++) {
int ans = 1;
for(int j = 0; j < i; j++) {
if(x[i] > x[j]) {
ans = max(ans, 1 + dp[j]);
}
}
dp[i] = ans;
}
int lis = 0;
for(int i = 0; i <= N; i++) {
if(dp[i] > lis) {
lis = dp[i];
pos = i; // track the last index of LIS (required to construct sequence)
}
}
return lis;
}
/**
Finding the sequence of LIS
**/
vector <int> listSequence;
void sequence() {
listSequence.clear();
listSequence.push_back(x[pos]);
for(int i = pos-1; i >= 0; i--) {
if( x[i] < x[pos] && dp[i] == dp[pos] -1) {
pos = i;
listSequence.push_back(x[i]);
}
}
for(int i = listSequence.size() -1; i >= 0; i--) cout << listSequence[i] << " ";
}
/**
Longest Increasing Subsequence in O(nlogk) time
Jane Alam Jan tutorial
**/
int I[30];
int LisNlogk() {
int i;
memset(I, INT_MAX, sizeof I);
I[0] = INT_MIN;
int trackPosition = 0;
int max = INT_MIN;
for(i = 0; i <= N; i++ ) {
int begin, end, mid;
begin = 0;
end = trackPosition;
while( begin <= end ) {
mid = ( begin + end ) / 2;
if( I[mid] < x[i] )
begin = mid + 1;
else
end = mid - 1;
}
// observe the binary search carefully, when the binary search ends
// begin > end and we put our item in I[begin]
I[begin] = x[i];
dp[i] = begin; // storing the LIS of every position
if(dp[i] > max) { // track the last index for later reconstruct the sequence
max = dp[i];
pos = i;
}
if( trackPosition < begin )
trackPosition = begin;
}
return trackPosition;
}
int LdsNlogk() {
// LDS can also be achieved by recersing the data array and then calculating LIS
int i;
memset(I, INT_MIN, sizeof I);
I[0] = INT_MAX;
int trackPosition = 0;
int Max = INT_MIN;
for(i = 0; i <= N; i++ ) {
int begin, end, mid;
begin = 0;
end = trackPosition;
while( begin <= end ) {
mid = ( begin + end ) / 2;
if( I[mid] > x[i] )
begin = mid + 1;
else
end = mid - 1;
}
// observe the binary search carefully, when the binary search ends
// begin > end and we put our item in I[begin]
I[begin] = x[i];
dp[i] = begin; // storing the LIS of every position
if(dp[i] > Max) { // track the last index for later reconstruct the sequence
Max = dp[i];
pos = i;
}
if( trackPosition < begin )
trackPosition = begin;
}
return trackPosition;
}
void decreasingSeq() {
listSequence.clear();
listSequence.push_back(x[pos]);
for(int i = pos-1; i >= 0; i--) {
if( x[i] > x[pos] && dp[i] == dp[pos] - 1) {
pos = i;
listSequence.push_back(x[i]);
}
}
for(int i = listSequence.size() -1; i >= 0; i--) cout << listSequence[i] << " ";
}