利用动态规划求解——给定矩阵求路径之和最大最小类问题

题1:下降路径最小和
给你一个 n x n 的 方形 整数数组 matrix ,请你找出并返回通过 matrix 的下降路径 的 最小和 。

下降路径 可以从第一行中的任何元素开始,并从每一行中选择一个元素。在下一行选择的元素和当前行所选元素最多相隔一列(即位于正下方或者沿对角线向左或者向右的第一个元素)。具体来说,位置 (row, col) 的下一个元素应当是 (row + 1, col - 1)、(row + 1, col) 或者 (row + 1, col + 1) 。

算法思路:
对于这类问题,给定矩阵求解最值,很明显可以使用动态规划来求解问题,有以下三个特殊位置:最左侧一列、最右侧一列、其他剩余列;对于最左侧一列元素只能从其正上方或者右上方来;对于最右侧一列只能从正上方或者左上方来;其他剩余元素可以从正上方、左上方和右上方来。
这里初始化二维数组时要注意,不能先初始化最左侧和最右侧然后再初始化剩余元素;因为在初始化最左侧或最右侧元素时,同时需要中间剩余元素的参与;那么我们只能一行一行进行存储元素。

算法实现:

class Solution {
    public static int minFallingPathSum(int[][] matrix) {
        //定义一格二维数组用来存储
        int[][] res = new int[matrix.length][matrix.length];
        //将res数组的第一行初始化
        for (int j=0;j<matrix[0].length;j++){
            res[0][j] = matrix[0][j];
        }
        //填充元素得一行一行来
        for (int i = 1;i<matrix.length;i++){
            //首先填充两边
            //最左侧
            res[i][0] = Math.min(res[i-1][0],res[i-1][1])+matrix[i][0];
            //最右侧
            res[i][matrix[0].length-1] = Math.min(res[i-1][matrix[0].length-1],res[i-1][matrix[0].length-2])+matrix[i][matrix[0].length-1];
            for (int j = 1;j<matrix[0].length-1;j++){
                //中间剩余元素
                res[i][j] = Math.min(Math.min(res[i-1][j],res[i-1][j-1]),res[i-1][j+1])+matrix[i][j];
            }
        }
        //在最后这一行找最小值
        int min = Integer.MAX_VALUE;
        for (int j = 0;j<matrix[0].length;j++){
            min = Math.min(min,res[matrix.length-1][j]);
        }
        return min;
    }
}

题2:礼物的最大价值
在一个 m*n 的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于 0)。你可以从棋盘的左上角开始拿格子里的礼物,并每次向右或者向下移动一格、直到到达棋盘的右下角。给定一个棋盘及其上面的礼物的价值,请计算你最多能拿到多少价值的礼物?

算法思路:
这里思路与上一题类似,只需要定义一个二维数组进行存储元素,然后逐步遍历即可。

算法实现:

class Solution {
    public int maxValue(int[][] grid) {
        //定义一个二维数组用来存储(总和)
        int[][] res = new int[grid.length][grid[0].length];
        //初始化左上角
        res[0][0] = grid[0][0];
        //对于第一行只能向右走
        for (int j=1;j<grid[0].length;j++){
            res[0][j] = res[0][j-1]+grid[0][j]; 
        }
        //对于第一列只能向下走
        for (int i = 1;i<grid.length;i++){
            res[i][0] = res[i-1][0]+grid[i][0];
        }
        //剩余元素找最大的
        for (int i = 1;i<grid.length;i++){
            for (int j = 1;j<grid[0].length;j++){
                res[i][j] = Math.max(res[i-1][j],res[i][j-1])+grid[i][j];
            }
        }
        return res[res.length-1][res[0].length-1];
    }
}

题3:最长不含重复字符的子字符串
——利用HashMap简化步骤
题目描述:
请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。

1)
输入: "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
(2)
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1

算法思路:
这道题,我采用的是通过HashMap存储已经遍历过的元素,当再次遇到相同元素时,此时可以利用HashMap判断是否有重复元素,当没有重复元素则将当前元素put入HashMap当中;遇到重复元素那么就清空HashMap,然后从上一次出发位置的下一个位置开始进行寻找。

ps:
这里需要注意当遍历到字符串的最后一个元素时,倘若还没有重复元素,那么就需要比较出和之前的哪个最大值。
同时更新下一次遍历起点的时候,由于start更新是在for循环里面,那么采用的时start++,而不是++start!(因为赋值后会在加一次,那么只需要上一次的就可以,加1会出现在for循环的更新表达式中)

算法实现:

class Solution {
    public static int lengthOfLongestSubstring(String s) {
        if (s.length()==1){
            return 1;
        }else if ("".equals(s)){
            return 0;
        }else{
            HashMap<Character,Integer> hash = new HashMap<>();
            int start = 0;
            int max = 0;
            for (int i = 0;i<s.length();i++){
                char c = s.charAt(i);
                //不重复元素
                if (!hash.containsKey(c)){
                    //将该元素放入
                    hash.put(c,1);
                    if (i==s.length()-1){
                        max = Math.max(max,hash.size());
                    }
                }else if (hash.containsKey(c)){
                    //包含重复元素
                    max = Math.max(max,hash.size());
                    hash.clear();
                    //从上次起始位置的下一位开始遍历
                    i = start++;
                }
            }
            return max;
        }
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 矩阵最小路径问题是指给定一个矩阵,从左上角出发,每次只能向右或向下走,到达右下角的最小路径和。这个问题可以使用动态规划法来解决。具体来说,我们可以定义一个二维数组dp,其中dp[i][j]表示从左上角到达(i,j)位置的最小路径和。则有以下状态转移方程: dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + matrix[i][j] 其中,matrix[i][j]表示矩阵中第i行第j列的元素值。最终的答案即为dp[m-1][n-1],其中m和n分别为矩阵的行数和列数。 ### 回答2: 矩阵最小路径问题指的是在一个矩阵中,从左上角到右下角的一条路径上,路径上所有元素值之和最小问题。这是一个典型的动态规划问题。 我们可以定义一个二维数组dp[m][n],其中dp[i][j]表示从矩阵的左上角到第i行j列的元素的最小路径和。显然,矩阵的左上角元素的最小路径和为其本身,即dp[0][0] = matrix[0][0]。 对于其他位置的元素,我们可以通过以下递推公式来求解: dp[i][j]=min(dp[i-1][j],dp[i][j-1])+matrix[i][j] 其中,dp[i-1][j]表示从左上角到dp[i-1][j]的路径最小和,dp[i][j-1]表示从左上角到dp[i][j-1]的路径最小和,matrix[i][j]表示当前位置的元素值。 最后,dp[m-1][n-1]就是从左上角到右下角的最小路径和。 具体的实现可以用两层循环来遍历矩阵,来更新dp数组。最终的时间复杂度为O(mn),空间复杂度也为O(mn)。 需要注意的是,在实际的求解过程中,为了避免dp数组中的元素被反复读取,可以在原始矩阵上进行原地修改,不需要新建一个dp数组。这样可以将空间复杂度降至O(1)。 总之,矩阵最小路径问题一个经典的动态规划问题。通过定义dp数组,以及递推公式,可以很好地解决这个问题。在实际中,需要注意如何优化空间复杂度,以及边界条件的处理。 ### 回答3: 矩阵最小路径问题是指在一个矩阵中,从左上角走到右下角,每次只能向下或向右走,经过的路径上数字之和最小值。这个问题可以使用动态规划算法来解决。 首先,我们可以定义一个二维的状态数组 dp[i][j],其中 dp[i][j] 表示从左上角走到位置 (i,j) 的最小路径和。对于第一行和第一列,它们只能向右或向下走,因此它们的状态值可以直接累加。即 dp[i][0] = sum(0,0->i,0),dp[0][j] = sum(0,0->0,j)。 对于其它位置 (i,j),它们可以从其上面或左边的位置转移而来。因此,我们有如下的转移方程: dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + matrix[i][j] 其中,matrix[i][j] 表示位置 (i,j) 上的数字。 最后,矩阵最小路径和就是 dp[m-1][n-1],其中 m 和 n 分别是矩阵的行数和列数。 使用动态规划算法求解矩阵最小路径问题的时间复杂度为 O(mn),空间复杂度为 O(mn)。因此,这个算法在面对大规模矩阵时可能会产生性能问题。为了解决这个问题,我们可以使用滚动数组来减小空间复杂度,或者使用贪心算法来近似解决问题

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值