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 普通全排列
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 要求去重的全排列
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)=(n−m)!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