【leetcode-37】【二分系列】300. 最长上升子序

题目描述

给定一个无序的整数数组,找到其中最长上升子序列的长度。

示例:
输入: [10,9,2,5,3,7,101,18]
输出: 4
解释: 最长的上升子序列是 [2,3,7,101],它的长度是 4。

说明:可能会有多种最长上升子序列的组合,你只需要输出对应的长度即可。
你算法的时间复杂度应该为 O(n2) 。

进阶: 你能将算法的时间复杂度降低到 O(n log n) 吗?

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-increasing-subsequence
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路

  • 动态规划版本,dp[i] 以nums[i]结尾的最长上升子序列的长度,目标是找到最大的dp[i]
    • 对于nums[i],需要遍历dp数组,如果nums[i]大于dp[k],则dp[i]的一个可能的值就是dp[k]+1
  • 贪心+二分查找法
    • d[i]表示长度为i+1的序列的最后一位数值.
    • d[i]单调递增,假如存在i < j, d[i] > d[j], 那么把d[j]的后k(j - i)位删掉,则此时d[k]小于d[i],但其实k=i,所以矛盾,得证d[i]单调递增。
    • 贪心之处在于希望长度是i的字符串的最后一位尽可能的小,这样就可以更容易的拼出长一点的上升子序列。
    • 在d[i]单调递增的情况下。
      • 如果当前元素比d的最末尾的一个元素都大,那么当前元素添加到d数组的末尾。
      • 如果当前元素小于d最末尾的一个元素,那么说明当前元素肯定可以替换d数组中的第k位,使得d[k]变小。
        -上述问题转变为如何在d中找到index,使得d[index - 1] < nums[i],d[index] > nums[i],这样就可以用nums[i]替换原d[index]的值,使得长度是index+1的上升子序列的最后一位变小。

代码

class Solution {
    
    
    public int lengthOfLIS(int[] nums) {
    
    
    	/** 动态规划版本
    	 * dp[i] 以nums[i]结尾的最长上升子序列的长度
    	 */
    	int[] dp = new int[nums.length];
    	dp[0] = 1;
    	int maxRes = 1;
    	for(int i = 1; i < nums.length; i++){
    
    
    		int maxVal = 1;
			for(int j = 0; j < i; j++){
    
    
				if(nums[i] > nums[j]){
    
    
					maxVal = Math.max(maxVal, dp[j]+1);
				}
			}
			dp[i] = maxVal;
			maxRes = Math.max(maxRes, dp[i]);
		}
		return maxRes;
		/**
		 * 二分 + 贪心
		 * d[i]表示长度为i+1的序列的最后一位数值
		 */
		int[] d = new int[nums.length];
		d[0] = nums[0];
		int left = 0, right = 0;
		for(int i = 1; i < nums.length; i++){
    
    
			if(nums[i] > d[right]){
    
    
				d[++right] = nums[i];
			} else {
    
    
				int rightTemp = right;
				while(left < right){
    
    
					int mid = (left + right) / 2;
					if(nums[i] > d[mid]){
    
    
						right = mid;
					} else if(nums[i] < d[mid]){
    
    
						left = mid + 1;
					} else {
    
    
						right = mid;
						break;
					}
				}
				d[right] = nums[i];
				right = rightTemp;
				left = 0;
			}
		}
		return right + 1;
    }
}

猜你喜欢

转载自blog.csdn.net/u010659877/article/details/106135326