【科学刷题】完全吃透回溯法所有题型

79. 单词搜索

79. 单词搜索

好像在剑指刷过

class Solution:
    def exist(self, board: List[List[str]], word: str) -> bool:
        m,n=len(board),len(board[0])
        L=len(word)
        def dfs(x, y, t):
            if t==L:
                return True
            if not (0<=x<m and 0<=y<n):
                return False
            if board[x][y]!=word[t]:
                return False
            board[x][y]='-'
            ans=dfs(x+1,y,t+1) or dfs(x,y+1,t+1) or dfs(x-1,y,t+1) or dfs(x,y-1,t+1)
            board[x][y]=word[t]
            return ans
        for x in range(m):
            for y in range(n):
                if dfs(x, y, 0):
                    return True
        return False

我是傻逼

TODO: 写一个更优雅的答案

1. 排列问题

回溯法最开始是【排列树】、【子集树】等内容,所以我们先从这方面开始说起。

全排列,可以认为是对数组A进行随机Shuffle后,对解空间进行遍历的操作。时间复杂度与解空间规模都是 O ( N ! ) O(N!) O(N!)

1.1 普通全排列

46. 全排列

class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        path = nums.copy()
        L = len(nums)
        ans = []

        def backtrace(t):
            if t == L - 1:
                ans.append(path.copy()) # 记得拷贝
                return 
            for i in range(t, L):
                path[i], path[t] = path[t], path[i]
                backtrace(t + 1)
                path[i], path[t] = path[t], path[i]

        backtrace(0)
        return ans

1.2 要求去重的全排列

47. 全排列 II

class Solution:
    def permuteUnique(self, nums: List[int]) -> List[List[int]]:
        ans = []
        n = len(nums)

        def backtrace(t):
            if t == n - 1:
                ans.append(nums[:]) # 记得拷贝
                return
            vis = set()
            for i in range(t, n):
                if nums[i] in vis:
                    continue
                vis.add(nums[i])
                nums[i], nums[t] = nums[t], nums[i]
                backtrace(t + 1)
                nums[i], nums[t] = nums[t], nums[i]

        backtrace(0)
        return ans

1.3 泛化的A(n, m)全排列

leetcode上没有这方面的题目,但是我们可以写一个泛化的 A ( n , m ) A(n,m) A(n,m)全排列

nums的长度为 n n n,我们从中考虑顺序地抽 m m m个数出来,时间复杂度与解空间规模都为 A ( n , m ) = n ! ( n − m ) ! A(n,m)=\frac{n!}{(n-m)!} A(n,m)=(nm)!n!

from typing import List


class Solution:
    def permuteGeneralization(self, nums: List[int], m) -> List[List[int]]:
        ans = []
        n = len(nums)

        def backtrace(t):
            if t == m:
                ans.append(nums[:m]) # 记得拷贝
                return
            for i in range(t, n):
                nums[i], nums[t] = nums[t], nums[i]
                backtrace(t + 1)
                nums[i], nums[t] = nums[t], nums[i]

        backtrace(0)
        return ans


if __name__ == '__main__':
    ans = Solution().permuteGeneralization([1, 2, 3, 4, 5], 2)
    print(ans)
    print(len
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值