【leetCode-DP】300. 最长上升子序列

 

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

示例:

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

   定义dp[i]为截止数组的第i个位置的最长上升序列,定义转移方程:

    for(int i = 0;i < len-1;i++) {
            for(int j = i+1;j < len;j++){
                if(nums[i] < nums[j]){
                    dp[j] = Math.max(dp[i]+1,dp[j]);
                }
            }
        }

 

    public static int lengthOfLIS(int[] nums) {
        int len = nums.length;
        if(len ==0){
            return 0;
        }
        int dp[] = new int[len+1];
        for(int i = 0;i < len;i++) {
            dp[i] = 1;
        }
        for(int i = 0;i < len-1;i++) {
            for(int j = i+1;j < len;j++){
                if(nums[i] < nums[j]){
                    dp[j] = Math.max(dp[i]+1,dp[j]);
                }
            }
        }
        int max = 0;
        for(int i  = 0;i < len;i++){
            max = Math.max(max,dp[i]);
        }
        System.out.println();
        return max;
    }

 


优化

上述算法是O(N^2)的,使用二分查找可以将时间复杂度优化为O(nlogn)

定义dp[]存放组成最长数组的序列,如果dp[cnt] < arr[i]则dp[++cnt]  = arr[i] 否则将dp[]数组中大于且接近arr[i]的一个数找出来 ,替换成arr[i]。

    public static int lengthOfLIS(int[] nums){
        int len = nums.length;
        if(len <=1){
            return len;
        }
        int[] dp = new int[len+1];
        dp[0] = nums[0];
        int cnt = 0;

        for(int i = 1;i < len;i++){
            if(dp[cnt] < nums[i]){
                dp[++cnt] = nums[i];
            } else {
                dp[upSearch(dp,cnt,nums[i])] = nums[i];
            }
        }
        return cnt+1;
    }

    private static int upSearch(int[] dp, int len, int x) {
        int mid,l=0;
        while(l<=len)
        {
            mid = (l+len)>>1;
            if(dp[mid] == x){
                return mid;
            }
            if(dp[mid]<x)
                l = mid+1;
            else
                len = mid-1;
        }
        return l;
    }

 

 

发布了615 篇原创文章 · 获赞 110 · 访问量 40万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章