目录
46. 全排列
# 46. 全排列
# 给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。
# 输入:nums = [1,2,3]
# 输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
from typing import List
class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
ans=[]
path=[]
valid=[False]*len(nums)
def dfs(h):
if(h==len(nums)):
ans.append(path[::])
return
for i in range(len(nums)):
if not valid[i]:
valid[i]=True
path.append(nums[i])
dfs(h+1)
valid[i]=False
path.pop()
dfs(0)
return ans
nums = [1,2,3]
s=Solution()
r=s.permute(nums)
print(r)
47. 全排列 II
# 47. 全排列 II
# 给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。
# 输入:nums = [1,1,2]
# 输出:
# [[1,1,2],
# [1,2,1],
# [2,1,1]]
from typing import List
class Solution:
def permuteUnique(self, nums: List[int]) -> List[List[int]]:
valid=[False]*len(nums)
path=[]
res=[]
nums.sort()
def dfs(h):
if(h==len(nums)):
res.append(path[::])
print(path)
return
for i in range(len(nums)):
if(i>0 and nums[i-1]==nums[i] and valid[i-1]):
continue
if not valid[i]:
valid[i]=True
path.append(nums[i])
dfs(h+1)
valid[i]=False
path.pop()
dfs(0)
return res
# nums = [1,2,3]
nums = [1,1,2]
s=Solution()
r=s.permuteUnique(nums)
print(r)
22. 括号生成
rom typing import List
# 这种方法超时了
# class Solution:
# def generateParenthesis(self, n: int) -> List[str]:
# res=[]
# t=[]
# s=['(',')']*n
# valid=[False]*2*n
# def is_valid(s1): #判断有效括号
# b=0
# for c in s1:
# if c=='(':
# b+=1
# else:
# b-=1
# if b<0:
# return False
# return b==0
#
# def dfs(h): #排列组合
# if(h==2*n):
# s1=''.join(t)
# if(is_valid(s1)):
# res.append(s1)
# return
#
# for i in range(len(s)):
# if not valid[i] :
# valid[i]=True
# t.append(s[i])
# dfs(h+1)
# t.pop()
# valid[i] = False
# dfs(0)
# return list(set(res))
class Solution:
def generateParenthesis(self, n: int) -> List[str]:
res=[]
t=[]
def is_valid(s1): #判断有效括号
b=0
for c in s1:
if c=='(':
b+=1
else:
b-=1
if b<0:
return False
return b==0
def dfs(h): #排列组合
if(h==2*n):
s1=''.join(t)
if(is_valid(s1)):
res.append(s1)
return
for i in '()':
t.append(i)
dfs(h+1)
t.pop()
dfs(0)
return list(set(res))
s=Solution()
r=s.generateParenthesis(3)
print(r)
39. 组合总和
# 39. 组合总和
# 给你一个 无重复元素 的整数数组candidates 和一个目标整数target,找出candidates中可以使数字和为目标数target 的 所有不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。
#
# candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。
#
# 对于给定的输入,保证和为target 的不同组合数少于 150 个。
# 输入:candidates = [2,3,6,7], target = 7
# 输出:[[2,2,3],[7]]
# 解释:
# 2 和 3 可以形成一组候选,2 + 2 + 3 = 7 。注意 2 可以使用多次。
# 7 也是一个候选, 7 = 7 。
# 仅有这两种组合。
class Solution:
# def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
def combinationSum(self, candidates, target):
ans=[]
def dfs(s,target,t):
if target==0:
ans.append(t)
if target<0:
return
for i in range(s,len(candidates)):
if i>0 and candidates[i-1]==candidates[i]:
continue
dfs(i,target-candidates[i],t+[candidates[i]])
dfs(0,target,[])
return ans
s=Solution()
candidates = [2,3,6,7]
target = 7
r=s.combinationSum(candidates,target)
print(r)
51. N皇后
# 51. N 皇后
# 按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。
#
# n皇后问题 研究的是如何将 n个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
#
# 给你一个整数 n ,返回所有不同的n皇后问题 的解决方案。
#
# 每一种解法包含一个不同的n 皇后问题 的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。
#
# 输入:n = 4
# 输出:[[".Q..","...Q","Q...","..Q."],["..Q.","Q...","...Q",".Q.."]]
# 解释:如上图所示,4 皇后问题存在两个不同的解法。
#按行开始遍历,每次选中某列;
#声明3个集合,c记录已经遍历过的行,d1记录满足i-j斜线的对角线;d2记录满足i+j的斜线
from typing import List
class Solution:
def solveNQueens(self, n: int) -> List[List[str]]:
res=[]
q=[-1]*n
t=['.']*n
c=set()
d1=set()
d2=set()
def gen_board():
board=[]
for k in range(n):
t[q[k]]='Q'
board.append(''.join(t))
t[q[k]]='.'
return board
def dfs(i):
if i==n:
print(q)
board=gen_board()
res.append(board)
else:
for j in range(n):
if j in c or i+j in d1 or i-j in d2:
continue
q[i]=j
c.add(j)
d1.add(i+j)
d2.add(i-j)
dfs(i+1)
c.remove(j)
d1.remove(i+j)
d2.remove(i-j)
dfs(0)
return res
s=Solution()
r=s.solveNQueens(4)
print(r)
40. 组合总和 II
# 40. 组合总和 II
# 给定一个候选人编号的集合candidates和一个目标数target,找出candidates中所有可以使数字和为target的组合。
# candidates中的每个数字在每个组合中只能使用一次。
# 注意:解集不能包含重复的组合。
# 输入: candidates = [10,1,2,7,6,1,5], target = 8,
# 输出:
# [
# [1,1,6],
# [1,2,5],
# [1,7],
# [2,6]
# ]
class Solution:
def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
candidates.sort()
ans=[]
t=[]
def dfs(s,target):
if target==0:
ans.append(t[::])
return
if target<0:
return
for i in range(s,len(candidates)):
if(i>s and candidates[i-1]==candidates[i]):
continue
t.append(candidates[i])
dfs(i+1,target-candidates[i])
t.pop()
dfs(0,target)
return ans
78. 子集
# 78. 子集
# 给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。
# 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。
# 输入:nums = [1,2,3]
# 输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
from typing import List
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
nums.sort()
res=[]
t=[]
def dfs(h):
res.append(t[::])
for i in range(h,len(nums)):
if(i>0 and nums[i-1]==nums[i]):
continue
t.append(nums[i])
dfs(i+1)
t.pop()
dfs(0)
return res
nums = [1,2,3]
s=Solution()
r=s.subsets(nums)
print(r)
37. 解数独
# 1、space 记录空格数的pair对,及对应的位置(i,j)
# 2、row[9][9] 标识行已经被添加的数
# 3、col[9][9] 标识列已经被添加的数
# 4、block[3][3][9] 标识控制块已经被添加的数
# 5、遍历一遍board,初始化space,row,col,block
class Solution:
# def solveSudoku(self, board: List[List[str]]) -> None:
# """
# Do not return anything, modify board in-place instead.
# """
def solveSudoku(self, board) :
def dfs(n):
nonlocal valid
if(n==len(space)):
valid=True
return
i,j=space[n]
for digit in range(9):
if(not row[i][digit] and not col[j][digit] and not block[i//3][j//3][digit]):
row[i][digit] = col[j][digit] = block[i//3][j//3][digit]=True
board[i][j]=str(digit+1)
dfs(n+1)
row[i][digit] = col[j][digit] = block[i//3][j//3][digit] = False
if valid:
return
space = []
row = [[False]*9 for _ in range(9)]
col = [[False]*9 for _ in range(9)]
block = [[[False]*9 for i in range(3)] for j in range(3)]
valid = False
for i in range(9):
for j in range(9):
if(board[i][j]=='.'):
space.append((i,j))
else:
digit=int(board[i][j])-1
row[i][digit] = True
col[j][digit] = True
block[i//3][j//3][digit] = True
dfs(0)
# print(board)
131. 分割回文串
# 131. 分割回文串
# 给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是 回文串 。返回 s 所有可能的分割方案。
# 回文串 是正着读和反着读都一样的字符串。
# 输入:s = "aab"
# 输出:[["a","a","b"],["aa","b"]]
from typing import List
class Solution:
def partition(self, s: str) -> List[List[str]]:
n=len(s)
f=[[True]*n for i in range(n)]
for i in range(n-1,-1,-1):
for j in range(i,n):
f[i][j]=f[i+1][j-1] and s[i]==s[j]
print(f)
ans=[]
t=[]
def dfs(i):
if i==len(s):
ans.append(t[::])
for j in range(i,len(s)):
if f[i][j]:
t.append(s[i:j+1])
dfs(j+1)
t.pop()
dfs(0)
return ans
s=Solution()
s1 = "aab"
r=s.partition(s1)
print(r)
93. 复原IP地址
# 93. 复原 IP 地址
# 有效 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0),整数之间用 '.' 分隔。
#
# 例如:"0.1.2.201" 和 "192.168.1.1" 是 有效 IP 地址,但是 "0.011.255.245"、"192.168.1.312" 和 "192.168@1.1" 是 无效 IP 地址。
# 给定一个只包含数字的字符串 s ,用以表示一个 IP 地址,返回所有可能的有效 IP 地址,这些地址可以通过在 s 中插入 '.' 来形成。你 不能 重新排序或删除 s 中的任何数字。你可以按 任何 顺序返回答案。
#
# 输入:s = "25525511135"
# 输出:["255.255.11.135","255.255.111.35"]
from typing import List
class Solution:
def restoreIpAddresses(self, s: str) -> List[str]:
for c in s:
if not (c in '0123456789'):
return []
res=set()
t=[]
def is_valid(tmp):
for c in tmp:
if c.startswith('0') and len(c)>1:
return False
if int(c)<0 or int(c)>255:
return False
return True
def dfs(b,h):
if(h==4):
if(b!=len(s)):
return
if(is_valid(t)):
res.add('.'.join(t))
return
for i in range(b+1,len(s)+1):
t.append(s[b:i])
dfs(i,h+1)
t.pop()
dfs(0,0)
return list(res)
s1 = "25525511135"
s=Solution()
r=s.restoreIpAddresses(s1)
print(r)
79. 单词搜索
# 79. 单词搜索
#
# 给定一个m x n 二维字符网格board 和一个字符串单词word 。如果word 存在于网格中,返回 true ;否则,返回 false 。
#
# 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
#
# 输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"
# 输出:true
class Solution:
# def exist(self, board: List[List[str]], word: str) -> bool:
def exist(self, board, word) :
def dfs(h,i,j):
if(h==len(word)):
return True
valid=False
if i>=0 and i<len(board) and j >=0 and j <len(board[0]) and not flag[i][j] and word[h]==board[i][j]:
flag[i][j] = True
valid=dfs(h+1,i+1,j) or dfs(h+1,i-1,j) or dfs(h+1,i,j-1) or dfs(h+1,i,j+1)
flag[i][j]=False
return valid
find=False
for i in range(len(board)):
for j in range(len(board[0])):
flag = [[False] * len(board[0]) for i in range(len(board))]
find=dfs(0,i,j)
if(find):
return True
return find
# board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]]
# word = "ABCCED"
# board = [["a","b"],["c","d"]]
# word = "acdb"
board =[["A","B","C","E"],["S","F","E","S"],["A","D","E","E"]]
word ="ABCESEEEFS"
s=Solution()
r=s.exist(board,word)
print(r)
44. 通配符匹配
# 44. 通配符匹配
# 给定一个字符串 (s) 和一个字符模式 (p) ,实现一个支持 '?' 和 '*' 的通配符匹配。
# '?' 可以匹配任何单个字符。
# '*' 可以匹配任意字符串(包括空字符串)。
# 两个字符串完全匹配才算匹配成功。
#
# 说明:
#
# s可能为空,且只包含从a-z的小写字母。
# p可能为空,且只包含从a-z的小写字母,以及字符?和*。
#
# 输入:
# s = "aa"
# p = "a"
# 输出: false
# 解释: "a" 无法匹配 "aa" 整个字符串。
# class Solution: #超时
# def isMatch(self, s: str, p: str) -> bool:
#
# if len(s) == 0 and len(p) == 0:
# return True
# if len(s) == 0 :
# i=0
# while(i<len(p)):
# if p[i]!='*':
# break
# i+=1
# if(i==len(p)):
# return True
# return False
# if len(p) == 0:
# return False
#
# if p[0] == '*':
# return self.isMatch(s, p[1:]) or self.isMatch(s[1:], p)
# elif (s[0] == p[0] or p[0] == '?'):
# return self.isMatch(s[1:], p[1:])
# else:
# return False
# class Solution: #超出时限
# def isMatch(self, s: str, p: str) -> bool:
#
# if len(s) == 0 and len(p) == 0:
# return True
# if len(p) == 0:
# return False
# # 判断是否为全*
# i = 0
# while (i < len(p)):
# if (p[i] != '*'):
# break
# i += 1
# print(s, p,i)
# if (i == len(p)):
# return True
#
# if len(s) == 0:
# return False
#
# if i > 0 and p[i - 1] == '*':
# return self.isMatch(s[1:], p[i - 1:]) or self.isMatch(s, p[i:])
# if (s[0] == p[0] or p[0] == '?'):
# return self.isMatch(s[1:], p[1:])
# return False
class Solution:
def isMatch(self, s: str, p: str) -> bool:
f=[[False]*(len(p)+1) for i in range(len(s)+1)]
f[0][0]=True
for j in range(1,len(p)+1):
if p[j-1]!='*':
break
f[0][j]=True
for i in range(1,len(s)+1):
for j in range(1,len(p)+1):
if s[i-1]==p[j-1] or p[j-1]=='?':
f[i][j]=f[i-1][j-1]
elif p[j-1]=='*':
f[i][j]=f[i][j-1] or f[i-1][j]
return f[-1][-1]
s=Solution()
s1="adceb"
p="*a*b"
r=s.isMatch(s1,p)
print(r)
77. 组合
# 77. 组合
# 给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。
# 你可以按 任何顺序 返回答案。
# 输入:n = 4, k = 2
# 输出:
# [
# [2,4],
# [3,4],
# [2,3],
# [1,2],
# [1,3],
# [1,4],
# ]
from typing import List
class Solution:
def combine(self, n: int, k: int) -> List[List[int]]:
res=[]
t=[]
def dfs(s,k,n):
if len(t)==k:
res.append(t[::])
return
if len(t)>k:
return
for i in range(s,n):
t.append(i+1)
dfs(i+1,k,n)
t.pop()
dfs(0,k,n)
return res
n = 4
k = 2
s=Solution()
r=s.combine(n,k)
print(r)