Day 33 動態規劃 Part10

12点不睡觉还想干啥?發表於2024-08-15

300. 最長遞增子序列

動態規劃的版本是挺好理解的,dp[i]代表了以第i個數字結尾的最長遞增子序列的長度,dp[0]顯然為1。dp如何更新呢? i > 0: dp[i] = 在i之前,最大的小於nums[i]的數nums[j] dp[i] = dp[j] + 1,所以就是需要找到比nums[i]小的最大的數,遍歷就可以得到。

class Solution {
    public int lengthOfLIS(int[] nums) {
        int[] dp = new int[nums.length];
        Arrays.fill(dp, 1);
        for(int i = 1; i < nums.length; i++)
            for(int j = 0; j < i; j++)  //找到比nums[i]小的
                if(nums[i] > nums[j]) dp[i] = Math.max(dp[i], dp[j] + 1);
        int max = 0;
        for(int num : dp) max = Math.max(num, max);
        return max;
    }
}

這個題解我也真是不想寫了,心裡好亂。看別人的題解吧,寫的很清楚。

class Solution {
    public int lengthOfLIS(int[] nums) {
        int[] l = new int[nums.length + 1];  
        // l[i]代表可以形成長度為i的遞增序列的末尾的最小值
        // 例如[2, 5, 3]可以形成長度為2的序列中[2, 3], [2, 5]末尾可以選3,或5,最小值為3,此時l[2] = 3
        int len = 1;
        l[1] = nums[0]; // l並非一開始就確定下來,而是不斷的更新,代表了已經遍歷的陣列中的滿足上述定義的l陣列
        for(int i = 1; i < nums.length; i++){
            if(nums[i] > l[len]) l[++len] = nums[i];  // 當遇到大於序列末尾最大值時,說明序列還能更長,更新l陣列和len
            else{
                l[binarySearch(l, 1, len, nums[i])] = nums[i];  // 找到l陣列中,第一個大於當前
            } 
        }
        return len;
    }
    public int binarySearch(int[] l, int left, int right, int val){ // 左閉右閉,找到第一個大於val的位置
        while(left <= right){
            int mid = (left + right) / 2;
            if(l[mid] == val) return mid;
            if(l[mid] > val) right = mid - 1;
            else left = mid + 1;
        }
        return left;
    }
}

674. 最長連續遞增序列

class Solution {
    public int findLengthOfLCIS(int[] nums) {
        int max = 1, len = 1;
        for(int i = 1; i < nums.length; i++){
            if(nums[i] > nums[i-1]) max = Math.max(max, ++len);
            else len = 1;
        }
        return max;
    }
}

718. 最長重複子陣列

我都不知道我為什麼要死磕那個滑動視窗的版本,雖然硬調出來了,但這要一次寫出來不犯錯對我來說有點不可能。動態規劃這個多好啊,清清楚楚,不容易犯錯。下次別這樣了。

class Solution {
    public int findLength(int[] nums1, int[] nums2) {
        int ans = 0;
        int n1 = nums1.length, n2 = nums2.length;
        int[][] dp = new int[n1+1][n2+1];
        for(int i = n1 - 1; i >= 0; i--){
            for(int j = n2 - 1; j >= 0; j--){
                dp[i][j] = nums1[i] == nums2[j] ? dp[i+1][j+1] + 1 : 0;
                ans = Math.max(ans, dp[i][j]);
            }
        }
        return ans;
    }
}

相關文章