LeetCode动态规划高频题(十三)

大家好,我是方圆
无它,唯手熟尔

题号

    • 5. 最长回文子串
    • 53. 最大子序和
    • 62. 不同路径
    • 64. 最小路径和
    • 70. 爬楼梯
    • 118. 杨辉三角
    • 300. 最长上升子序列
    • 746. 使用最小花费爬楼梯
    • 1277. 统计全为1的正方形子矩阵


5. 最长回文子串

LeetCode动态规划高频题(十三)_第1张图片

class Solution {
    public String longestPalindrome(String s) {
        //特殊情况,单个字符时直接返回回文串
        int len = s.length();
        if(len < 2){
            return s;
        }

        //用来保存最大长度和初始位置
        int maxLen = 1;
        int begin = 0;
        //用二维数组对角线上半部分保存是否为回文串
        boolean[][] dp = new boolean[len][len];
        char[] charArray = s.toCharArray();

        for(int i = 0;i < len;i++){
            //对角线为单字符,全部为true
            dp[i][i] = true;
        }

        //开始动态规划
        for(int j = 1;j < len;j++){
            for(int i = 0;i < j;i++){
                if(charArray[i] != charArray[j]){
                    dp[i][j] = false;
                }else{
                    //这种情况是首位相同、长度为2或为3的情况
                    if(j - i < 3){
                        dp[i][j] = true;
                    }else{
                        //长度较长的时候,判断它的字串是不是回文串
                        //若字串是回文串,那么就是;否则,反之
                        dp[i][j] = dp[i + 1][j - 1];
                    }
                }

                //当出现回文串的时候,便进行判断,是否需要记录长度
                if(dp[i][j] && j - i + 1 > maxLen){
                    maxLen = j - i + 1;
                    begin = i;
                }
            }
        }

        return s.substring(begin,begin + maxLen);
    }
}

53. 最大子序和

LeetCode动态规划高频题(十三)_第2张图片

class Solution {
    public int maxSubArray(int[] nums) {
        int len = nums.length;
        //判空
        if(len == 0){
            return 0;
        }

        //进行动态规划,dp[i] 用来存储
        //i结尾的和
        int[] dp = new int[len];
        dp[0] = nums[0];

        for(int i = 1;i < len;i++){
            //当dp[i - 1] >= 0时,对当前值有增益
            if(dp[i - 1] >= 0){
                dp[i] = nums[i] + dp[i - 1];
            }else{
                //没有增益的时候
                dp[i] = nums[i];
            }
        }

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

        return res;
    }
}

62. 不同路径

LeetCode动态规划高频题(十三)_第3张图片
LeetCode动态规划高频题(十三)_第4张图片

class Solution {
    public int uniquePaths(int m, int n) {
        int[][] res = new int[m][n];

        //将第一行第一列全部置为1
        for(int i = 0;i < n;i++){
            res[0][i] = 1;
        }
        for(int j = 0;j < m;j++){
            res[j][0] = 1;
        }

        //计算到达每个格子的路线数量
        //int[m][n] = int[m - 1][n] + int[m][n - 1]
        for(int i = 1;i < m;i++){
            for(int j = 1;j < n;j++){
                res[i][j] = res[i - 1][j] + res[i][j - 1];
            }
        }

        return res[m - 1][n - 1];
    }
}

64. 最小路径和

LeetCode动态规划高频题(十三)_第5张图片

class Solution {
    public int minPathSum(int[][] grid) {
        for(int i = 0;i < grid.length;i++){
            for(int j = 0;j < grid[0].length;j++){
                if(i == 0 && j == 0){
                    continue;
                }else if(i == 0){
                    grid[0][j] = grid[0][j] + grid[0][j - 1];
                }else if(j == 0){
                    grid[i][0] = grid[i][0] + grid[i - 1][0];
                }else{
                    grid[i][j] = grid[i][j] + Math.min(grid[i][j - 1],grid[i - 1][j]);
                }
            }
        }
        return grid[grid.length - 1][grid[0].length - 1];
    }
}

70. 爬楼梯

LeetCode动态规划高频题(十三)_第6张图片

class Solution {
    //思路:只能每次爬一层楼或者爬两层楼
    //我们举一个简单的例子,爬上5层楼
    //那么我们只能在3层楼上爬2步,或者4层楼上爬1步
    //爬上5楼为爬上3层楼的次数加上爬上四层楼的次数
    public int climbStairs(int n) {
        //创建数组,对应的下标存储爬到对应楼层的方法
        int dp[] = new int[n + 1];

        //这里需要注意,dp[0] = 1,因为爬上两层楼时需要为2,需要它为加数
        dp[0] = 1;
        dp[1] = 1;
        for(int i = 2;i < n + 1;i++){
            dp[i] = dp[i - 1] + dp[i - 2];
        }

        return dp[n];
    }
}

118. 杨辉三角

LeetCode动态规划高频题(十三)_第7张图片

class Solution {
    public List<List<Integer>> generate(int numRows) {
        List<List<Integer>> triangle = new ArrayList<>();
        //判空
        if(numRows == 0){
            return triangle;
        }

        //第一行只有一个1
        triangle.add(new ArrayList<Integer>());
        triangle.get(0).add(1);

        //从第2行进行循环
        for(int i = 1;i < numRows;i++){
            List<Integer> row = new ArrayList<>();
            //上一行
            List<Integer> preRow = triangle.get(i - 1);

            //开头一个1
            row.add(1);
            //判断两个1之间是否有中间项,有则进行循环
            for(int j = 1;j < i;j++){
                row.add(preRow.get(j) + preRow.get(j - 1));
            }
            //末尾一个1
            row.add(1);

            triangle.add(row);
        }
        return triangle;
    }
}

300. 最长上升子序列

LeetCode动态规划高频题(十三)_第8张图片

class Solution {
    public int lengthOfLIS(int[] nums) {
        //dp中每个元素代表以该元素结尾的最大升序子序列长度
        int[] dp = new int[nums.length];
        //对数组中每个元素进行赋值,最短是本身,为1
        Arrays.fill(dp,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);
            }
        }

        int res = 0;
        for(int i = 0;i < dp.length;i++){
            res = Math.max(res,dp[i]);
        }
        return res;
    }
}

746. 使用最小花费爬楼梯

LeetCode动态规划高频题(十三)_第9张图片

class Solution {
    public int minCostClimbingStairs(int[] cost) {
        if(cost.length == 0){
            return 0;
        }
        if(cost.length == 1){
            return cost[0];
        }

        int[] dp = new int[cost.length];
        dp[0] = cost[0];
        dp[1] = cost[1];

        for(int i = 2;i < cost.length;i++){
            dp[i] = Math.min(dp[i - 1] + cost[i],dp[i - 2] + cost[i]);
        }

        return Math.min(dp[cost.length - 1],dp[cost.length - 2]);
    }
}

1277. 统计全为1的正方形子矩阵

LeetCode动态规划高频题(十三)_第10张图片
LeetCode动态规划高频题(十三)_第11张图片

class Solution {
    public int countSquares(int[][] matrix) {
        int m = matrix.length;
        int n = matrix[0].length;

        int[][] dp = new int[m][n];
        int res = 0;

        //对第一行和第一列进行预处理
        for(int i = 0;i < m;i++){
            res += dp[i][0] = matrix[i][0];
        }

        for(int j = 0;j < n;j++){
            res += dp[0][j] = matrix[0][j];
        }
        //当(0,0)为1时,需要减去一个个数
        if(matrix[0][0] == 1){
            res--;
        }

        for(int i = 1;i < m;i++){
            for(int j = 1;j < n;j++){
                if(matrix[i][j] == 1){
                dp[i][j] = Math.min(Math.min(dp[i - 1][j],dp[i][j - 1]),dp[i - 1][j - 1]) + 1;
                res += dp[i][j];
                }
            }
        }
        
        return res;
    }
}

终于可以开开心心安安稳稳的写博客儿拉!

你可能感兴趣的:(LeetCode)