【LeetCode】62. Unique Paths 解题报告(Python & C++)

901 篇文章 209 订阅

作者: 负雪明烛
id: fuxuemingzhu
个人博客: http://fuxuemingzhu.cn/


题目地址:https://leetcode.com/problems/unique-paths/description/

题目描述:

A robot is located at the top-left corner of a m x n grid (marked ‘Start’ in the diagram below).

The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked ‘Finish’ in the diagram below).

How many possible unique paths are there?

此处输入图片的描述

题目大意

给出了一个m * n的地图,上面有个机器人位于左上角,现在他想到达右下角。它每次只能向右边或者下边走一步,问能到达右下角的方式有多少种。

解题方法

方法一:组合公式

这个题搞明白之后其实就是一个排列组合中的组合类型的题目。

在总数为m + n - 2中的数目中挑选n - 1个位置放竖着的走。也就是我们说的C(m + n - 2)(n -1)的问题。

组合公式的计算方式为:此处输入图片的描述,使用公式计算出结果就行了。

时间复杂度是O(m + n),空间复杂度是O(1)。

class Solution(object):
    def uniquePaths(self, m, n):
        """
        :type m: int
        :type n: int
        :rtype: int
        """
        total = m + n - 2
        v = n - 1
        def permutation(m, n):
            son = 1
            for i in range(m, m - n, -1):
                son *= i
            mom = 1
            for i in range(n, 0, -1):
                mom *= i
            return son / mom
        return permutation(total, min(v, total -v))

方法二:记忆化搜索

到达某个位置的次数怎么计算?可以想到是到达这个位置上面的位置的次数+到达坐标的次数。这里需要说明的是因为两个这个机器人走的方向只能向右或者向下,所以它到达上边位置和左边位置的次数中没有交集,所以可以直接相加。

把问题分解之后,我们就想到了用递归,那么递归的终止条件是什么?明显地机器人到达第一行或者第一列任意位置的可能性方式只有一种!那就是一直向这个方向走!

另外使用了记忆化数组保存已经走过位置的次数,可以加快运算。

时间复杂度是O(m * n),空间复杂度是O(m * n)。超过了99%的提交。

class Solution(object):
    def uniquePaths(self, m, n):
        """
        :type m: int
        :type n: int
        :rtype: int
        """
        memo = [[0] * n for _ in range(m)]
        return self.dfs(m - 1, n - 1, memo)
        
    def dfs(self, m, n, memo):
        if m == 0 or n == 0:
            return 1
        if memo[m][n]:
            return memo[m][n]
        up = self.dfs(m - 1, n, memo)
        left = self.dfs(m, n - 1, memo)
        memo[m][n] = up + left
        return memo[m][n]

方法三:动态规划

看到上面记忆化搜索的方法就知道这个题同样可以使用动态规划解决。第一行第一列的所有方式只有1种,到达其他位置的方式是这个位置上面 + 这个位置左边用DP的话,和上面记忆化搜索差不多。

时间复杂度是O(m * n),空间复杂度是O(m * n)。超过了17%的提交,没有上面搜索快。

class Solution(object):
    def uniquePaths(self, m, n):
        """
        :type m: int
        :type n: int
        :rtype: int
        """
        dp = [[0] * n for _ in range(m)]
        for i in range(m):
            dp[i][0] = 1
        for i in range(n):
            dp[0][i] = 1
        for i in range(1, m):
            for j in range(1, n):
                dp[i][j] = dp[i][j - 1] + dp[i - 1][j]
        return dp[m - 1][n - 1]

上面是把dp初始化为0,也可以换初始化为1:

class Solution(object):
    def uniquePaths(self, m, n):
        """
        :type m: int
        :type n: int
        :rtype: int
        """
        dp = [[1] * n for _ in range(m)]
        for i in range(m):
            for j in range(n):
                if i == 0 or j == 0:
                    continue
                dp[i][j] = dp[i][j - 1] + dp[i - 1][j]
        return dp[m - 1][n - 1]

使用C++代码如下,这次是把所有的位置都初始化成0,除了机器人刚开始所在的位置[1,1]设置成了1.

class Solution {
public:
    int uniquePaths(int m, int n) {
        vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));
        dp[1][1] = 1;
        for (int i = 1; i < m + 1; ++i) {
            for (int j = 1; j < n + 1; ++j) {
                if (i == 1 && j == 1) continue;
                dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
            }
        }
        return dp[m][n];
    }
};

日期

2018 年 2 月 19 日
2018 年 10 月 18 日
2018 年 12 月 29 日 —— 2018年剩余电量不足1%

你好!对于LeetCode上的问题994.腐烂的橘子,你可以使用Python来解决。下面是一个示例代码: ```python from collections import deque def orangesRotting(grid): # 记录网格的行数和列数 row, col = len(grid), len(grid[0]) # 定义四个方向:上、下、左、右 directions = [(-1, 0), (1, 0), (0, -1), (0, 1)] # 使用队列来保存腐烂的橘子的位置 queue = deque() # 记录新鲜橘子的数量 fresh_count = 0 # 遍历整个网格,初始化队列和新鲜橘子的数量 for i in range(row): for j in range(col): if grid[i][j] == 2: # 腐烂的橘子 queue.append((i, j)) elif grid[i][j] == 1: # 新鲜橘子 fresh_count += 1 # 如果新鲜橘子的数量为0,直接返回0 if fresh_count == 0: return 0 # 初始化分钟数 minutes = 0 # 开始进行BFS,直到队列为空 while queue: # 记录当前分钟数下,队列中的元素数量 size = len(queue) # 遍历当前分钟数下的所有腐烂的橘子 for _ in range(size): x, y = queue.popleft() # 遍历四个方向 for dx, dy in directions: nx, ny = x + dx, y + dy # 判断新位置是否在网格内,并且是新鲜橘子 if 0 <= nx < row and 0 <= ny < col and grid[nx][ny] == 1: # 将新鲜橘子变为腐烂状态 grid[nx][ny] = 2 # 将新鲜橘子的位置加入队列 queue.append((nx, ny)) # 新鲜橘子的数量减1 fresh_count -= 1 # 如果当前分钟数下,没有新鲜橘子了,结束循环 if fresh_count == 0: break # 每遍历完一层,分钟数加1 minutes += 1 # 如果最后还有新鲜橘子,返回-1,否则返回分钟数 return -1 if fresh_count > 0 else minutes ``` 你可以将给定的网格作为参数传递给`orangesRotting`函数来测试它。请注意,该代码使用了BFS算法来遍历橘子,并计算腐烂的分钟数。希望能对你有所帮助!如果有任何疑问,请随时问我。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值