-
Notifications
You must be signed in to change notification settings - Fork 0
/
LongestIncreasingSubsequence.cpp
145 lines (138 loc) · 4.11 KB
/
LongestIncreasingSubsequence.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
#include <algorithm>
#include <stdio.h>
using std::max;
const int maxLen = 100;
int ls[maxLen];//length of each list ending at each index
/**
* NOTE: Gets the length of the list ENDING at each index.
* To get the length of each list STARTING at each index, reverse your list
* and run LDSS on it.
* @param nums
* @return
*/
int lis(int* nums, int len){
int maxs = 1;
for(int i = 0; i < len; i++){
ls[i]=1;
for(int j = 0; j < i; j++){
if(nums[i]>nums[j]){
ls[i] = max(ls[i], ls[j]+1);
maxs = max(maxs, ls[i]);
}
}
}
return maxs;
}
/**
* Same as above, but more useful because you get the numbers in the sequence
* The index of the maximum element is maxi, and you work back from there
* using prev
* Remember to reverse the list and run longest decreasing sequence if you
* want to get the list is the right order
*/
int prev[30];
int maxi;
int lis(int len){
int maxs = 1;
maxi=0;
for(int i = 0; i < len; i++){
ls[i]=1;
prev[i]=-1;
for(int j = 0; j < i; j++){
if(isIn(boxes[i],boxes[j])){
if(ls[j]+1>ls[i]){
prev[i]=j;
ls[i] = ls[j]+1;
}
if(ls[i]>maxs){
maxs = ls[i];
maxi = i;
}
}
}
}
return maxs;
}
const int maxWeights = 100;
const int maxLoad = 100;
int m[maxWeights][maxLoad+1];
/**
* Given each element has a load and a weight, you want to stack elements on
* top of each other
* Returns the number of elements that can be stacked
* m[i][j] = length of longest sequence
* Ending at element i
* With a max load of j
* @return
*/
int lisWeighted(int* weight, int* load, int len, int loadLen){
int maxs = 1;
for(int i = 0 ; i < len; i++){
for(int j = 0 ; j <= loadLen; j++){
if(i==0)
m[i][j]=j<=load[i]?1:0;
else if (j<=load[i] && j+weight[i]<=loadLen)
m[i][j]=max(m[i-1][j], 1+m[i-1][j+weight[i]]);
else if (j<=load[i])
m[i][j]=max(m[i-1][j], 1);
else
m[i][j]=m[i-1][j];
maxs = max(maxs,m[i][j]);
}
}
return maxs;
}
const int maxLength = 100;
int b[maxLength];//index of numbers that form lis
int p[maxLength];
/**
* Optimized version of the algorithm
* Finds longest strictly increasing subsequence. O(n log k) algorithm.
*/
int lisOptim(int* nums, int len) {
int u, v,bsize;
if (len==0) return 0;
b[0]=0;
bsize = 1;
//the ending point
for (int i = 1; i < len; i++){
// If next element nums[i] is greater than last element of current
// longest subsequence nums[b.back()], just push it at back of "b"
// and continue
if (nums[b[bsize-1]] < nums[i]){
//REPLACE WITH CUSTOM COMPARISON HERE IF NEEDED
p[i] = b[bsize-1];
b[bsize]=i;
bsize++;
continue;
}
// Binary search to find the smallest element referenced by b which
// is just bigger than nums[i]
// Note : Binary search is performed on b (and not a).
//Size of b is always <=k and hence contributes O(log k) to complexity.
for (u = 0, v =bsize-1; u < v;){
int c = (u + v) / 2;
if (nums[b[c]] < nums[i]) u=c+1; else v=c;
//REPLACE WITH CUSTOM COMPARISON HERE IF NEEDED
}
// Update b if new value is smaller then previously referenced value
if (nums[i] < nums[b[u]]){//REPLACE WITH CUSTOM COMPARISON IF NEEDED
if (u > 0)
p[i] = b[u-1];
b[u]= i;
}
}
for (u = bsize-1, v = b[bsize-1];u>=0; b[u]= v, v = p[v],u--);
return bsize;
}
int main() {
const int len = 5;
int nums[len] = {0,10,5,20,15};
int seqLen = lis(nums,len);
printf("length of lis unOptimized: %d\n",seqLen);
seqLen = lisOptim(nums, len);
printf("length of lis optimized %d\n", seqLen);
for(int i =0; i<seqLen;i++)
printf("%d ",nums[b[i]]);
printf("\n");
}