代码随想录-2023/08/19

115 阅读2分钟

动态规划 --- 序列问题

53.最大子数组和

解题思路: 动态规划

  1. 定义dp数组含义: 以i结尾的最大子数组和
  2. 当加上当前位置的连续子数组和 > 当前元素时, 代表前缀和有益, 需要保留
  3. 当加上当前位置的连续子数组和 < 当前元素时, 代表前缀和无益, 需要舍弃
  4. 不是以终点为最优解, 需要在动规过程中不断记录最大值

代码:

class Solution {
    public int maxSubArray(int[] nums) {
        int n = nums.length;
        int[] dp = new int[n];
        dp[0] = nums[0];
        int ans = nums[0];
        for(int i=1; i < n; i++){
            dp[i] = Math.max(dp[i-1] + nums[i], nums[i]);
            ans = Math.max(ans, dp[i]);
        }
        return ans;
    }
}

1143.最长公共子序列

解题思路: 动态规划

  1. 比较两个字符串, 数组, 子序列的公共部分: 二维dp
  2. dp数组含义:ch1i-1结尾, ch2j-1结尾的最长公共子序列长度为dp[i][j]
  3. 当两个比较位置的字符相等时: dp[i][j] = dp[i-1][j-1] + 1
  4. 当不相等时, 需要延续其之前相等的状态:dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1])

代码:

class Solution {
    // 两个数组, 字符串, 序列求公共问题: 二维dp
    public int longestCommonSubsequence(String text1, String text2) {
        char[] ch1 = text1.toCharArray();
        char[] ch2 = text2.toCharArray();
        // dp数组含义: ch1以i+1结尾, ch2以j+1结尾的最长公共子序列长度为dp[i][j]
        int[][] dp = new int[ch1.length + 1][ch2.length + 1];
        int ans = 0;
        for(int i=1; i <= ch1.length; i++){
            for(int j=1; j<=ch2.length; j++){
                if(ch1[i-1] == ch2[j-1]){
                    dp[i][j] = dp[i-1][j-1] + 1;
                }else dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]);
                ans  = Math.max(ans, dp[i][j]);
            }
        }

        return ans;

    }
}

1035.不相交的线

解题思路: 动态规划 --- 与1035题完全相同

代码:

class Solution {
    public int maxUncrossedLines(int[] nums1, int[] nums2) {
        int m = nums1.length, n = nums2.length;
        int[][] dp = new int[m + 1][n + 1];
        for(int i=1; i <= m; i++){
            for(int j=1; j <= n; j++){
                if(nums1[i-1] == nums2[j-1]){
                    dp[i][j] = dp[i][j-1] + 1;
                }else dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]);
            }
        }

        return dp[m][n];
    }
}