动态规划之子序列问题

导读:本篇文章讲解 动态规划之子序列问题,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

 动态规划之子序列问题 大多是需要二维动态规划的

遍历顺序大多是从上往下 从左往右,特别的回文子串和最长回文子序列,是从下往上。

目录

300.最⻓递增⼦序列

674. 最⻓连续递增序列

 贪心

动态规划:

718. 最⻓重复⼦数组

1143.最⻓公共⼦序列

 53. 最⼤⼦序和

392.判断⼦序列

115.不同的⼦序列

583. 两个字符串的删除操作

72. 编辑距离

647. 回⽂⼦串

516.最⻓回⽂⼦序列

5, 最长回文子串


300.最⻓递增⼦序列

动态规划之子序列问题

class Solution {
  public int lengthOfLIS(int[] nums) {
        if(nums.length == 0) return 0;
        int[] dp = new int[nums.length];
        int res = 0;
        Arrays.fill(dp, 1);// 默认是1 
        for(int i = 0; i < nums.length; i++) {
            for(int j = 0; j < i; j++) {
                if(nums[j] < nums[i]) dp[i] = Math.max(dp[i], dp[j] + 1);
            }
            res = Math.max(res, dp[i]);
        }
        return res;
    }


}

674. 最⻓连续递增序列

动态规划之子序列问题

 贪心

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

基于本题贪心的思路,可以联想到LeetCode原题: 122. 买卖股票的最佳时机 II,贪心的思路为:因为交易次数不受限,我们可以把所有的上坡全部收集到,然后求和,其结果一定是利益最大化

作者:ju-ren-zhang
链接:https://leetcode-cn.com/problems/longest-continuous-increasing-subsequence/solution/tu-biao-si-lu-kan-bu-dong-ni-da-wo-ji-ba-7fr7/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

动态规划:

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

718. 最⻓重复⼦数组

动态规划之子序列问题

 动态规划之子序列问题

class Solution {
    public int findLength(int[] nums1, int[] nums2) {
        int n = nums1.length;
        int m = nums2.length;
        int[][] dp = new int[n + 1][m + 1]; // dp[i][j]表示A的前i项与B的前j项的最长重复子数组长度
        int ans = 0;
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                if (nums1[i - 1] == nums2[j - 1]) {
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                    ans = Math.max(ans,dp[i][j]);
                }
            }
        }
        return ans;
    }
}

1143.最⻓公共⼦序列

动态规划之子序列问题

动态规划之子序列问题

class Solution {
    public int longestCommonSubsequence(String text1, String text2) {
        int n1 = text1.length(),n2 = text2.length();
        int[][] dp = new int[n1+1][n2+1];
        for (int i = 1; i <= n1; i++) {
            for (int j = 1; j <= n2; j++) {
                char c1 = text1.charAt(i-1);
                char c2 = text2.charAt(j-1);
                dp[i][j] = c1==c2 ? dp[i-1][j-1]+1 : Math.max(dp[i-1][j],dp[i][j-1]);
            }
        }
        return dp[n1][n2];
    }
}

 53. 最⼤⼦序和

动态规划之子序列问题

class Solution {
    public int maxSubArray(int[] nums) {
        // if(nums==null||nums.length==0)return null;
        if(nums.length==1)return nums[0];
        int pre = nums[0];
        int max = Integer.MIN_VALUE;
        max = Math.max(max,pre);
        
        for (int i = 1; i < nums.length; i++) {
            pre = Math.max(nums[i],nums[i]+pre);
            // i依次增加  pre会依次变成以对应位置结尾的子序列和的最大值
            // max存储 所有位置序列和的最大值
            max = Math.max(max,pre);
        }
        return max;
    }
}

392.判断⼦序列

动态规划之子序列问题

这道题⽬算是编辑距离的⼊⻔题⽬(毕竟这⾥只是涉及到减法),也是动态规划解决的经典题型。
可以用双指针来做
class Solution {
    public boolean isSubsequence(String s, String t) {
        int slen = s.length(), tlen = t.length();
        if(slen>tlen) return false;
        if(slen==0)return true;
        int sptr = 0, tptr = 0;
        while(tptr<tlen){
            if(t.charAt(tptr)==s.charAt(sptr) && (++sptr==slen)) {
                return true;
            }
            tptr++;
        }
        return false;
    }
}

 动态规划也可

动态规划之子序列问题

115.不同的⼦序列

动态规划之子序列问题

class Solution {
    public int numDistinct(String s, String t) {
        int[][] dp = new int[t.length() + 1][s.length() + 1];
        for (int j = 0; j < s.length() + 1; j++) dp[0][j] = 1;
        for (int i = 1; i < t.length() + 1; i++) {
            for (int j = 1; j < s.length() + 1; j++) {
                if (t.charAt(i - 1) == s.charAt(j - 1)) dp[i][j] = dp[i - 1][j - 1] + dp[i][j - 1];
                else dp[i][j] = dp[i][j - 1];
            }
        }
        return dp[t.length()][s.length()];
    }
}

583. 两个字符串的删除操作

动态规划之子序列问题

 用 最长公共子序列即可

class Solution {
    public int minDistance(String word1, String word2) {
        int m = word1.length(), n = word2.length();
        int[][] dp = new int[m + 1][n + 1];
        for (int i = 1; i <= m; i++) {
            char c1 = word1.charAt(i - 1);
            for (int j = 1; j <= n; j++) {
                char c2 = word2.charAt(j - 1);
                if (c1 == c2) {
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                } else {
                    dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
                }
            }
        }
        int lcs = dp[m][n];
        return m - lcs + n - lcs;
    }
}

72. 编辑距离

动态规划之子序列问题

public int minDistance(String word1, String word2) {
    int m = word1.length();
    int n = word2.length();
    int[][] dp = new int[m + 1][n + 1];
    // 初始化
    for (int i = 1; i <= m; i++) {
        dp[i][0] =  i;
    }
    for (int j = 1; j <= n; j++) {
        dp[0][j] = j;
    }
    for (int i = 1; i <= m; i++) {
        for (int j = 1; j <= n; j++) {
            // 因为dp数组有效位从1开始
            // 所以当前遍历到的字符串的位置为i-1 | j-1
            if (word1.charAt(i - 1) == word2.charAt(j - 1)) {
                dp[i][j] = dp[i - 1][j - 1];
            } else {
                dp[i][j] = Math.min(Math.min(dp[i - 1][j - 1], dp[i][j - 1]), dp[i - 1][j]) + 1;
            }
        }
    }
    return dp[m][n];
}

647. 回⽂⼦串

动态规划之子序列问题

动态规划之子序列问题

516.最⻓回⽂⼦序列

动态规划之子序列问题

class Solution {
    public int longestPalindromeSubseq(String s) {
        int n = s.length();
        int[][] dp = new int[n][n];// 初始化为0 表示 s[i:j]最长回文子串长度为0
        for (int i = n - 1; i >= 0; i--) {
            dp[i][i] = 1;
            char c1 = s.charAt(i);
            for (int j = i + 1; j < n; j++) {
                char c2 = s.charAt(j);
                if (c1 == c2) {
                    dp[i][j] = dp[i + 1][j - 1] + 2;
                } else {
                    // j位置的字符和i的不相等,那么就不会在dp[i + 1][j - 1] 增加
                    // 此时最大的字符串长度要不然算上它也就是  dp[i + 1][j] 要不就去掉它dp[i][j - 1]
                    dp[i][j] = Math.max(dp[i + 1][j], dp[i][j - 1]);
                }
            }
        }
        return dp[0][n - 1];
    }
}

5, 最长回文子串

class Solution {
    public String longestPalindrome(String s) {
        // ababa 求最长公共子串  
        int len = s.length();
        String result = "";
        //              i < 9  0 1 2 3 4 5 6 7 8
        for (int i = 0; i < len * 2 - 1; i++) {
            int left = i / 2;// 依次遍历len * 2个中心  0 0 1 1 2 2 3 3 4
            int right = left + i % 2;           ///   0 1 1 2 2 3 3 4 4   
            while (left >= 0 && right < len && s.charAt(left) == s.charAt(right)) {
                String tmp = s.substring(left, right + 1);
                if (tmp.length() > result.length()) {
                    result = tmp;
                }
                left--;
                right++;
            }
        }
        return result;

    }
    
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/92848.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!