【LeetCode】Sama的个人记录_28

 

 

【Q64】(md) 最小路径和
 
给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
 
说明:每次只能向下或者向右移动一步。
 
示例:

输入: [ [1,3,1], [1,5,1], [4,2,1] ]
输出: 7

>>> 题目本身达不到middle难度。
>>> 但是三元表达式处理边界,是个很好的习惯。还是要提一下。
>>> 另外,当在某个维度,仅仅是 i - 1 或 j - 1 的时候,即跨度仅仅是1/1列的话,就应该立即想到滚动数组
class Solution {
     
    public int minPathSum(int[][] grid) {
     
        int m = grid.length;
        int n = grid[0].length;

        int[][] dp = new int[m][n];
        for(int i = 0; i < m; i++){
     
            for(int j = 0; j < n; j++){
     
                if(i ==0 && j == 0){
     
                    dp[i][j] = grid[i][j];
                    continue;
                }
                dp[i][j] = Math.min(i -1 >= 0 ? dp[i - 1][j] : Integer.MAX_VALUE, j -1 >= 0 ? dp[i][j - 1] : Integer.MAX_VALUE) + grid[i][j];
            }
        }

        return dp[m - 1][n -1];

    }
}
// 滚动数组压缩空间复杂度。直接在上面的代码上删掉第一个维度就可以,不要上来就想着压缩。
class Solution {
     
    public int minPathSum(int[][] grid) {
     
        int m = grid.length;
        int n = grid[0].length;

        int[] dp = new int[n];
        for(int i = 0; i < m; i++){
     
            for(int j = 0; j < n; j++){
     
                if(i ==0 && j == 0){
     
                    dp[j] = grid[i][j];
                    continue;
                }
                dp[j] = Math.min(i - 1 >= 0 ? dp[j] : Integer.MAX_VALUE, j - 1 >= 0 ? dp[j - 1] : Integer.MAX_VALUE) + grid[i][j];
            }
        }

        return dp[n -1];

    }
}

 

 

【Q1025】(ez) 除数博弈(Alice and Bob)
 
爱丽丝和鲍勃一起玩游戏,他们轮流行动。爱丽丝先手开局。
 
最初,黑板上有一个数字 N 。在每个玩家的回合,玩家需要执行以下操作:
 
选出任一 x,满足 0 < x < N 且 N % x == 0 。 用 N - x 替换黑板上的数字 N 。
如果玩家无法执行这些操作,就会输掉游戏。
 
只有在爱丽丝在游戏中取得胜利时才返回 True,否则返回 false。假设两个玩家都以最佳状态参与游戏。
 
示例 1: 输入:2 输出:true   解释:爱丽丝选择 1,鲍勃无法进行操作。
示例 2: 输入:3 输出:false   解释:爱丽丝选择 1,鲍勃也选择 1,然后爱丽丝无法进行操作。
 
提示: 1 <= N <= 1000

class Solution {
     
    /**
     *【动态规划】
     *
     * dp值的含义为:先手是否必胜
     * 动态转移的核心思想是:比如此时N=6(求dp[6]),我取走2,那么我的胜率就是!dp[4]
     */
    public boolean divisorGame(int N) {
     
        boolean dp[] = new boolean[N + 1];
        for(int i = 2; i < N + 1; i++){
     
            for(int j = 1; j < i; j++){
     
                if(i % j == 0 && !dp[i - j]){
     
                    dp[i] = true;
                    break;
                }
            }
        }
        return dp[N];
    }
}
class Solution {
     
	/*
	* 其实,只要N为偶数,则先手必胜;N为奇数,先手必败
	*/
    public boolean divisorGame(int N) {
     
        return N % 2 == 0 ? true : false;
    }
}

 

 

【Q329】(hd) 矩阵中的最长递增路径
 
给定一个整数矩阵,找出最长递增路径的长度。
 
对于每个单元格,你可以往上,下,左,右四个方向移动。 你不能在对角线方向上移动或移动到边界外(即不允许环绕)。
 
示例 :

输入: nums = [ [9, 9, 4],
        [6, 6, 8],
        [2, 1, 1] ]
输出: 4 :
最长递增路径为 [1, 2, 6, 9]。

class Solution_329 {
     
    /**
     *【记忆化递归】
     *
     * 即【DFS】 + 【记忆化数组】,极其典型
     *
     * 思路:从每一个节点出发,进行DFS遍历————这并不困难
     *      但是如果每个点作为一次递归的起点,必然超时。因此使用记忆化数组对递归结果进行记录————如果已经有记录,直接返回
     *
     * 举例:
     * 1 → 3 → 5 → 6 → 10
     * 1 → 2 → 3 → 4 → 5 → 6 → 10
     * (5为两条路径的交点,第二条路径递归到5时,直接使用第一条路径在5时的递归结果)
     */
    public int longestIncreasingPath(int[][] matrix) {
     
        if(matrix.length == 0){
     
            return 0;
        }

        int maxLen = 0;
        int row = matrix.length;
        int col = matrix[0].length;
        memo = new int[row][col];

        for(int i = 0; i < row; i++){
     
            for(int j = 0; j < col; j++){
     
                maxLen = Math.max(maxLen, dfs(matrix, i, j));
            }
        }
        return maxLen;
    }

    private int[][] memo;
    private int[][] move = {
     {
     0, 1}, {
     0, -1}, {
     1, 0}, {
     -1, 0}};

    private int dfs(int[][] matrix, int i, int j){
           // dfs到了此处
        if(memo[i][j] > 0){
     
            return memo[i][j];
        }

        memo[i][j]++;
        for(int k = 0; k < move.length; k++){
     
            int newI = i + move[k][0];
            int newJ = j + move[k][1];
            if(newI >= 0 && newI < matrix.length && newJ >= 0 && newJ < matrix[0].length && matrix[newI][newJ] > matrix[i][j]){
     
                memo[i][j] = Math.max(memo[i][j], dfs(matrix, newI, newJ) + 1);
            }
        }
        return memo[i][j];
    }
}

 
 

 

 

 

 

 

 

 

 

 
 

 

 

Qs from https://leetcode-cn.com
♥ loli suki
♠ end

你可能感兴趣的:(Leetcode,leetcode,算法,动态规划)