leetcode 300. 最长递增子序列

题目链接
思路一:动态规划
分析:假设就一个元素,那么长度肯定就是1,如果是两个元素,那么只有第二个元素比第一个元素小的时候,才会是2,否则,长度还是1。
声明dp[i]:表示以nums[i]结尾的最大递增子序列。
那么存在nums[j] 代码:

class Solution {
    public int lengthOfLIS(int[] nums) {
        int n = nums.length;
        int[] dp = new int[n];
        //记录答案
        int max = 1;
        //初始化dp,也就是每个元素以自身结尾的最大长度肯定大于等于1
        Arrays.fill(dp,1);
        //以为right为结尾的一层循环
        for(int right = 1; right< n;right++){
        	//从0到right-1查询所有比nums[right]小的元素
            for(int left = 0; left <right; left++){
                if(nums[right]>nums[left]){
                	//状态转移,将right加在left后面,那么长度就是dp[left]+1
                    dp[right] = Math.max(dp[right],dp[left]+1);
                }
            }
            //每次找完right后,都更新一次max
            max =Math.max(max,dp[right]);
        }
        return max;
    }
}

思路二:贪心+二分查找
分析:考虑一个贪心,如果我们要递增子序列尽可能的长,那么我们要让递增子序列增的尽可能的慢,所以我们就可以让同样长的子序列中,最末尾的数字尽可能的小。
我们可以维护一个数组,dp;dp[i]表示长度为i的递增子序列末尾最小的数是dp[i]。
举例:
nums={1,100,101,102,2,3,4,5,6};
dp[1] = 1;
dp[2] = 100;
dp[3] = 101;
dp[4] = 102;

此时遍历到了2,二分查找dp中第一个比2大的下标,然后修改这个数
也就是
dp[2] = 2;
依次类推
dp[3] = 3
dp[4] = 4
dp[5] = 5
dp[6] = 6
然后dp最大的一个长度,
也就是6,这个6指的是下标那个6;
代码:

class Solution {
    public int lengthOfLIS(int[] nums) {
        int n = nums.length;
        int[] dp = new int[n+1];
        Arrays.fill(dp,10000);
        dp[1] = nums[0];
        int index =1;
        for(int i = 1 ; i <n ; i++){
        	//k表示以长度为k
            int k = binarySearch(dp,index,nums[i])+1;
            //长度为K的最小的结尾是dp[k]
            dp[k] = Math.min(dp[k], nums[i]);
            //index是最远的下标,也即是最大的下标,也就是最长子序列的长度
            index = Math.max(index, k);
        }
        return index;
    }
	
	//在dp中二分查找在[0,right]区间内小于key的下标
    public int binarySearch(int[] dp, int right, int key){
        int left = 1;
        int mid = 0;
        while(left<right){
            mid = (left+right)/2;
            if(dp[mid]<key){
                left = mid+1;
            }else if(dp[mid] > key){
                right = mid - 1;
            }else{
                return mid-1;
            }
        }
        if(dp[left]>=key){
            return left-1;
        }
        return left;
    }
}

你可能感兴趣的:(算法,动态规划,贪心算法,最长递增子序列,二分查找,数组处理)