【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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章