刷Leetcode算法的第十七天

序言

今天是刷LT的一天,好好干饭,好好努力,好好加油哦!

Leetcode题目–576:出界的路径数
给定一个 m × n 的网格和一个球。球的起始坐标为 (i,j) ,你可以将球移到相邻的单元格内,或者往上、下、左、右四个方向上移动使球穿过网格边界。但是,你最多可以移动 N 次。找出可以将球移出边界的路径数量。答案可能非常大,返回 结果 mod 109 + 7 的值。

例子如下:

输入: m = 2, n = 2, N = 2, i = 0, j = 0
输出: 6

在这里插入图片描述

方法一:动态规划

class Solution:
    def findPaths(self, m, n, maxMove, startRow, startColumn):
        #创建一个网格
        dp = [[0] * n for _ in range(m)]

        for k in range(maxMove):
            cur =  [[0] * n for _ in range(m)]
            for m_ in range(m):
                for n_ in range(n):
                
                    if m_ == 0: 
                    #如果这个格子在第一行,则明显可以往上走出去,所以v1 = 1 。
                        v1 = 1 
                    else: v1 = dp[m_- 1][n_]
                    #如果格子不在第一行,则得往上看一行
                    #---------------------

                    if m_ == M-1:
                    #如果格子在最后一行,则可以往下可以走出去,所以v2= 1
                        v2 = 1
                    else: v2 = dp[m_+1][n_]
                    #如果格子不在最后一行,则往下看一行
                    #---------------------

                    if n_ == 0:
                    #如果在第一列,则可以往左走出去 
                        v3 = 1
                    else: v3 = dp[m_][n_-1]
                    #---------------------

                    if n_ == n -1:
                    #如果在最后一列,则可以往右走出去
                        v4 = 1
                    else: v4 = dp[m_][n_+1]
                    #---------------------
                    cur[m_][n_] = (v1+v2+v3+v4)%(10**9 + 7)
            dp = cur  
        return dp[startRow][startColumn] 

方法二:BFS广度优化搜索

    def findPaths( m, n, maxMove, startRow, startColumn):
        #创建网格,使之数值都是0
        dp = [[0]*n for _ in range(m)]
        #定义方向 direction 
        dire = ((1,0),(-1,0),(0,1),(0,-1))

        for _ in range(maxMove):
            cur = [[0]*n for _ in range(m)]
            #cur表示 for k = 1,2,3,4,,,maxMove的每一个状态 
            for i in range(m):
                for j in range(n):
                    for di,dj in dire:
                        ni = i + di 
                        nj = j + dj 
                        if ni >= m or ni < 0 or nj >= n or nj < 0:
                            cur[i][j] += 1 
                        else: 
                            cur[i][j] = (cur[i][j] + dp[ni][nj]) %(10**9 + 7)
            dp = cur 
        return dp[startRow][startColumn]

LT62:不同的路径
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。
问总共有多少条不同的路径?

例子如下
在这里插入图片描述

输入:m = 3, n = 7
输出:28
输入:m = 3, n = 3
输出:6
输入:m = 3, n = 2
输出:3

方法一:动态规划

从start point开始,到网格的第一行和第一列都是只有一条路
然后往下走,会发现某一格子的路径数是由 左边格子数 加上 上面格子数 非常重要的信息
因此,可以用动态规划来做,除去第一行和第一列,某一格子的路径数是 等于 左边格子数 + 上面格子数

    def uniquePaths(m, n):
        #创建网格
        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-1][j] + dp[i][j-1]
        return dp[m-1][n-1]

方法二:bfs 广度优先搜索

我们已经知道规律
除去第一行和第一列,某一格子的路径数是 等于 左边格子数 + 上面格子数
所以可以考虑用bfs来做,可以加快速度:

class Solution:
    def uniquePaths(self, m: int, n: int) -> int:

        dp = [[0]*n for _ in range(m)]
        return self.bfs(m-1,n-1,dp)

    def bfs(self,i,j,dp):
        if i == 0 or j == 0:
            return 1 
        
        if dp[i][j]:
        #如果dp[i][j]是0或者false的话 不return
            return dp[i][j] 

        left = self.bfs(i-1,j,dp)
        right = self.bfs(i,j-1,dp)
        dp[i][j] = left + right 
        return dp[i][j]

题目三:

题目688–马在棋盘上
已知一个 NxN 的国际象棋棋盘,棋盘的行号和列号都是从 0 开始。即最左上角的格子记为 (0, 0),最右下角的记为 (N-1, N-1)。
现有一个 “马”(也译作 “骑士”)位于 (r, c) ,并打算进行 K 次移动。 如下图所示,国际象棋的 “马” 每一步先沿水平或垂直方向移动 2 个格子,然后向与之相垂直的方向再移动 1 个格子,共有 8 个可选的位置

在这里插入图片描述

现在 “马” 每一步都从可选的位置(包括棋盘外部的)中独立随机地选择一个进行移动,直到移动了 K 次或跳到了棋盘外面。求移动结束后,“马” 仍留在棋盘上的概率

例子如下

输入: 3, 2, 0, 0
输出: 0.0625
解释: 
输入的数据依次为 N, K, r, c
第 1 步时,有且只有 2 种走法令 “马” 可以留在棋盘上(跳到(1,2)或(2,1))。对于以上的两种情况,各自在第2步均有且只有2种走法令 “马” 仍然留在棋盘上。
所以 “马” 在结束后仍在棋盘上的概率为 0.0625

这道题跟之前足球出界的问题很像,不过足球是想要出界,这里是求 不会出界的可能性。
所以解题思路跟足球出界的差不多,也是把每一次的状态记录下来,然后再叠加
最后来一个sum up所有的可能性
代码如下:

class Solution:
    def knightProbability(self, n: int, k: int, row: int, column: int) -> float:
        dp = [[0]*n for _ in range(n)]
        dire = ((1,2),(2,1),(2,-1),(1,-2),(-1,2),(-2,1),(-2,-1),(-1,-2))
        dp[row][column] = 1
        for _ in range(k):
            cur = [[0]*n for _ in range(n)]
            #记录每一次的状态 
            for i in range(n):
                for j in range(n):
                    for di,dj in dire:
                        ni = i + di 
                        nj = j + dj 
                        if ni>=n or ni < 0 or nj >= n or nj < 0: 
                            continue 
                        else: 
                            cur[ni][nj] += dp[i][j] 
            dp = cur 
        return sum(map(sum, dp)) / float(8 ** k)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jianafeng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值