Leetcode刷题全记录,每题都有长进(medium 61-90)

62 不同路径

在这里插入图片描述标准的动态规划,每一步数都可以从上一步的状态转移过来。

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

对于动态规划还是注意初始条件,和转移方程。
以及对于二维dp,还是看清楚mn的具体,分清楚行和列。

64 最小路径和

在这里插入图片描述依然是一道dp问题,这类图表dp已经找到一些敲门,可以对比这个代码和上一题的代码。有很强的相似性。

class Solution(object):
    def minPathSum(self, grid):
        """
        :type grid: List[List[int]]
        :rtype: int
        """
        m = len(grid)
        n = len(grid[0])
        dp = [[float('inf') for i in range(n)] for i in range(m)]
        dp[0][0] = grid[0][0]
        for i in range(m):
            for j in range(n):
                if i > 0:
                    dp[i][j] = min(dp[i][j], dp[i-1][j]+grid[i][j])
                if j > 0:
                    dp[i][j] = min(dp[i][j], dp[i][j-1]+grid[i][j])
        return dp[m-1][n-1]

代码精妙之处:

  1. 需要注意的就是,看到dp表初始为0还是inf比较合适
  2. 如果希望节省空间,可以改为grid[i][j] = min(dp[i][j], dp[i-1][j]+grid[i][j])直接在原坐标上修改

75 颜色分类

在这里插入图片描述又是看到题目就傻了,没有找到思路,似然想到这种想要减少复杂度的题目应该用指针或许可以解决。但是我没找到突破口。
这个三指针方法有点绕。用三个指针p0,p2cur来分别表示第一个1,2的最左边界(不含2)和当前考虑的元素。
本解法的思路是沿着数组移动 curr指针,

  1. nums[cur] = 0,则将其与 nums[p1]互换并且移动p1cur
  2. nums[cur] = 2 ,则与 nums[p2]互换,并且移动p2
  3. nums[cur]=1,则继续移动cur
class Solution(object):
    def sortColors(self, nums):
        """
        :type nums: List[int]
        :rtype: None Do not return anything, modify nums in-place instead.
        """
        cur = 0
        p1 = 0
        p2 = len(nums)-1
        while cur<=p2:
            if nums[cur] == 0:
                nums[p1], nums[cur] = nums[cur], nums[p1]
                cur += 1
                p1 += 1
            elif nums[cur] == 2:
                nums[p2], nums[cur] = nums[cur], nums[p2]
                p2 -= 1
            elif nums[cur] == 1:
                cur += 1     

一道精妙的算法题,难点在于每次判断结果以后,指针如何进行迭代

78 子集

在这里插入图片描述还是一道回溯(dfs)题目,套用前面的模板就可以ac

class Solution(object):
    def subsets(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        res = []
        nums.sort()
        
        def backtrack(now, index):
            res.append(now[:])
            for i in range(index, len(nums)):
                now.append(nums[i])
                backtrack(now, i+1)
                now.pop()
        backtrack([], 0)
        return res

对于这类题目,最优方法对了在优化上可以没必要过分苛求。

79 单词搜索

一道很不错的DFS+回溯算法的题目,值得二刷复习的。
在这里插入图片描述看到题目,思路大概限定在了BFS,DFS, 和dp上。如果是dp,子问题就是‘ABCCE’是否存在,感觉还是不解决根本问题。
在BFS和DFS选择的话,bfs会遇到一个问题就是多源搜索的话,不好保存每次已经走过的路程。

什么问题适合用bfs和dfs?我分享下我对这个题目的思考过程。 这个题目如果使用BFS有两种思路,一个是多源起点开始bfs,也就是从每个’A’都同步开始执行广度搜索,但是这样有一个问题每次不好标记那些是已经加入队列的不能再次使用,因为是同时多支搜索的。如果是单源bfs,就和weiwei回答一样,bfs占用的空间比较大。 加上,这个题目要求只要找到一个通路就可以返回,更适合一条路走到黑的dfs。 如果问有几种不同的方式组成‘ABCDE’,那其实bfs和dfs的复杂就是一样的了。

废话不多说了,直接上代码。

class Solution(object):
    def exist(self, board, word):
        """
        :type board: List[List[str]]
        :type word: str
        :rtype: bool
        """
        def dfs(r, l, n,mark):
            if n == len(word):
                return True
              # 向上搜索
            if r>0 and board[r-1][l]==word[n] and mark[r-1][l]==0:
                mark[r-1][l] = 1
                #!!!注意标记,这个位置已经被使用了
                if dfs(r-1, l, n+1,mark):
                    return True
                # !!结束一次失败的搜索以后,需要及时释放
                mark[r-1][l] = 0
            if r<h-1 and board[r+1][l] == word[n] and mark[r+1][l]==0:
                mark[r+1][l] = 1
                if dfs(r+1, l, n+1,mark):
                    return True
                mark[r+1][l] = 0
            if l>0 and board[r][l-1]==word[n] and mark[r][l-1]==0:
                mark[r][l-1] = 1
                if dfs(r, l-1, n+1,mark):
                    return True
                mark[r][l-1] = 0
            if l<w-1 and board[r][l+1] == word[n] and mark[r][l+1]==0:
                mark[r][l+1] = 1
                if dfs(r, l+1, n+1, mark):
                    return True
                mark[r][l+1] = 0
            return False 
        

        h = len(board)
        w = len(board[0])
        mark = [[0 for i in range(w)]for j in range(h)]
        for i in range(h):
            for j in range(w):
                if board[i][j] == word[0]:
                    mark[i][j] = 1
                    if dfs(i,j, 1,mark):
                        return True
                    mark[i][j] =0
        return False

代码亮点:

  1. 还是注意这个题目需要标记已经使用的元素
  2. 如何实现剪枝,全在于每次只要True就返回
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值