代码随想day34|62不同路径63不同路径II|01笔记

82 阅读1分钟
  • 62不同路径

  • 代码随想录 (programmercarl.com)
  • 第一印象

  • 类似于爬楼梯的思路,到达当前方块的方法是从上面来的和从左面方块来的和。因此可以使用动态规划。
  • 讲解观后感

  • 可通过以为滚动数组的方式节省空间,但是不是很容易理解。主要是分开计算行和列的和值,并不断刷新当前显示的行(或列)。
  • 数论方法通过推理转化为组合问题,也是十分巧妙,但不容易想到。
  • 解题代码

  • 二维
  •     func uniquePaths(m int, n int) int {
            dp := make([][]int, m)
        
            for i := range dp {
        		dp[i] = make([]int, n)
        		dp[i][0] = 1
        	}
            for j:=0;j<n;j++{
                dp[0][j] = 1
            }
            for mi:=1;mi<m;mi++ {
                for ni:=1;ni<n;ni++{
                    dp[mi][ni] = dp[mi-1][ni] + dp[mi][ni-1]
                }
            }
            return dp[m-1][n-1]
        
        
        }
    
  • 一维
  •     func uniquePaths(m int, n int) int {
            dp := make([]int, n)
        
            
            for i:=0;i<n;i++{
                dp[i] = 1
            }
            for mi:=1;mi<m;mi++ {
                for i:=1;i<n;i++{
                    dp[i]+=dp[i-1]
                }
            }
            return dp[n-1]
        
        
        }
    
  • 数论C++
  •     class Solution {
        public:
            int uniquePaths(int m, int n) {
                long long numerator = 1; // 分子
                int denominator = m - 1; // 分母
                int count = m - 1;
                int t = m + n - 2;
                while (count--) {
                    numerator *= (t--);
                    while (denominator != 0 && numerator % denominator == 0) {
                        numerator /= denominator;
                        denominator--;
                    }
                }
                return numerator;
            }
        };
    
  • 63不同路径II

  • 代码随想录 (programmercarl.com)
  • 第一印象

  • 最开始的想法是可以算出走到障碍物的路线数。然后用无障碍的路线数减掉即可。但是这样无法处理多个障碍物路线存在重复的情况。
  • 讲解观后感

  • 利用保持存在障碍的格子路线控制为零的方法,并注意初始化时的情况。在进行递推公式推导的时候,在障碍物存在的格子跳过赋值即可。
  • 解题代码

  •     func uniquePathsWithObstacles(obstacleGrid [][]int) int {
        	m, n := len(obstacleGrid), len(obstacleGrid[0])
        	//如果在起点或终点出现了障碍,直接返回0
        	if obstacleGrid[m-1][n-1] == 1 || obstacleGrid[0][0] == 1 {
        		return 0
        	}
        	// 定义一个dp数组
        	dp := make([][]int, m)
        	for i, _ := range dp {
        		dp[i] = make([]int, n)
        	}
        	// 初始化, 如果是障碍物, 后面的就都是0, 不用循环了
        	for i := 0; i < m && obstacleGrid[i][0] == 0; i++ {
        		dp[i][0] = 1
        	}
        	for i := 0; i < n && obstacleGrid[0][i] == 0; i++ {
        		dp[0][i] = 1
        	}
        	// dp数组推导过程
        	for i := 1; i < m; i++ {
        		for j := 1; j < n; j++ {
        			// 如果obstacleGrid[i][j]这个点是障碍物, 那么dp[i][j]保持为0
        			if obstacleGrid[i][j] != 1 {
        				// 否则我们需要计算当前点可以到达的路径数
        				dp[i][j] = dp[i-1][j] + dp[i][j-1]
        			}
        		}
        	}
        	return dp[m-1][n-1]
        }
    
  • 一维C++
  •     class Solution {
        public:
            int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
                if (obstacleGrid[0][0] == 1)
                    return 0;
                vector<int> dp(obstacleGrid[0].size());
                for (int j = 0; j < dp.size(); ++j)
                    if (obstacleGrid[0][j] == 1)
                        dp[j] = 0;
                    else if (j == 0)
                        dp[j] = 1;
                    else
                        dp[j] = dp[j-1];
        
                for (int i = 1; i < obstacleGrid.size(); ++i)
                    for (int j = 0; j < dp.size(); ++j){
                        if (obstacleGrid[i][j] == 1)
                            dp[j] = 0;
                        else if (j != 0)
                            dp[j] = dp[j] + dp[j-1];
                    }
                return dp.back();
            }
        };