题解 | #最长上升子序列(一)#
最长上升子序列(一)
https://www.nowcoder.com/practice/5164f38b67f846fb8699e9352695cd2f
很对人讲了二分的过程,但没有讲为什么,我搜了一些用自己的话描述出来,有不恰当的地方请见谅。
新建一个 low 数组,low中的数组有序,且都是low数组最后数插入后目的数组最小值,这样才能发现最长的子序列。
例如:1 4 7 2 5 9 10 3 的最短子序列为 1 4 7 9 10 或 1 2 5 9 10 或 1 4 5 9 10,low数组就为1 2 3 9 10
更新过程如下:
A[1] = 1,把1放进B[1],此时B[1] = 1,B[ ] = {1},len = 1
A[2] = 4,把4放进B[2],此时B[2] = 4,B[ ] = {1,4},len = 2
A[3] = 7,把7放进B[3],此时B[3] = 7,B[ ] = {1,4,7},len = 3
A[4] = 2,因为2比4小,所以把B[2]中的4替换为2,此时B[ ] = {1,2,7},len = 3
A[5] = 5,因为5比7小,所以把B[3]中的7替换为5,此时B[ ] = {1,2,5},len = 3
A[6] = 9,把9放进B[4],此时B[4] = 9,B[ ] = {1,2,5,9},len = 4
A[7] = 10,把10放进B[5],此时B[5] = 10,B[ ] = {1,2,5,9,10},len = 5
A[8] = 3,因为3比5小,所以把B[3]中的5替换为3,此时B[ ] = {1,2,3,9,10},len = 5C语言代码:
int Index(int *, int, int);
int LIS(int* arr, int arrLen ) {
// write code here
if(arrLen <= 1) return arrLen;
int low[arrLen];
low[0] = arr[0];
int len = 1;
for(int il = 0, ia = 1; ia != arrLen;ia++){
if(low[il] < arr[ia]){
low[++il] = arr[ia];
len++;
}else{
int index = Index(low, il, arr[ia]);
low[index] = arr[ia];
}
}
return len;
}
int Index(int *arr, int il, int target){
int lo = 0, hi = il;
while(lo < hi){
int mid = lo + (hi - lo)/2;
if(arr[mid] >= target){
hi = mid;
}else{
lo = mid + 1;
}
}
return lo;
}
