贪心+二分查找:最长上升子序列(3.14 leetcode每日打卡)
Posted ZLJ_Nice
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了贪心+二分查找:最长上升子序列(3.14 leetcode每日打卡)相关的知识,希望对你有一定的参考价值。
给定一个无序的整数数组,找到其中最长上升子序列的长度。
示例:
输入: [10,9,2,5,3,7,101,18]
输出: 4
解释: 最长的上升子序列是 [2,3,7,101],它的长度是 4。
输出: 4
解释: 最长的上升子序列是 [2,3,7,101],它的长度是 4。
说明:
可能会有多种最长上升子序列的组合,你只需要输出对应的长度即可。
你算法的时间复杂度应该为 O(n2) 。
进阶: 你能将算法的时间复杂度降低到 O(n log n) 吗?
思路:emmm,还没学动态规划,就看了一下官方思路写了一下,贪心和二分查找,二分查找主要用于优化速率。用一个dp数组保存最长子序列,从第一个数据开始,如果第二个数据比第一个数据小,如果大,就直接放到后边,然后第二个数据就顶替第一个数据,如果后边有数据,在dp数组中间,则这个数据就直接把刚好比它大的那个数据顶替掉,emmmm说不清楚。。。
直接上实例:
首先dp[0] = 10 然后发现nums[1]<dp[0],所以直接用nums[1]作为dp[0]重新开始,遇到nums[2]<dp[0],同理,遇到nums[3] = 5,放到后边,遇到nums[4] = 3,它大于2小于5,直接顶替5,以此类推
dp数组中的元素变化:
dp[numsSize] = 10
dp[numsSize] = 9
dp[numsSize] = 2
dp[numsSize] = 2 5
dp[numsSize] = 2 3
dp[numsSize] = 2 3 7
dp[numsSize] = 2 3 7 101
dp[numsSize] = 2 3 18 101
ok ok 返回长度即可。
int lengthOfLIS(int* nums, int numsSize) { if(numsSize == 0) return 0; int dp[numsSize]; int p = -1; dp[++p] = nums[0]; for(int i=0; i<numsSize; i++) { if(nums[i] > dp[p]) { dp[++p] = nums[i]; } else //进行二分查找法 { int low = 0; //指向头部 int high = p; //指向尾部 int ptr = 0; while(low <= high) { int mid = (high+low)/2; //指向中间 if(nums[i] > dp[mid]) { ptr = mid; low = mid+1; } else if(nums[i] <= dp[mid]) { high = mid-1; } } if(dp[ptr] >= nums[i]) { dp[ptr] = nums[i]; } else { dp[ptr+1] = nums[i]; } } } return p+1; }
以上是关于贪心+二分查找:最长上升子序列(3.14 leetcode每日打卡)的主要内容,如果未能解决你的问题,请参考以下文章
AcWing 895 最长上升子序列 - (线性DP) or (贪心+二分优化)