目录
组合(N个数里面按一定规则找出k个数的集合)
组合不强调元素顺序,排列强调元素顺序
77. 组合
class Solution(object):
def combine(self, n, k):
"""
:type n: int
:type k: int
:rtype: List[List[int]]
"""
# index为即将确定第index位数字
# pre为之前已经排序过的数字
# 这种组合方式默认从小到大排列,因此ans中的数字应该是由小到大的
def backtracking(index, ans, res, pre):
if index == k:
res.append(ans)
for i in range(pre+1, n+1):
backtracking(index + 1, ans + [i], res, i)
ans = []
res = []
backtracking(0, ans, res, 0)
return res
17. 电话号码的数字组合
class Solution(object):
def letterCombinations(self, digits):
"""
:type digits: str
:rtype: List[str]
"""
if not digits:
return []
hashtable = {
"2": "abc",
"3": "def",
"4": "ghi",
"5": "jkl",
"6": "mno",
"7": "pqrs",
"8": "tuv",
"9": "wxyz",
}
def backtrack(index, ans, res):
if index == len(digits):
res.append("".join(ans))
else:
digit = digits[index]
for letter in hashtable[digit]:
backtrack(index + 1, ans + [letter], res)
ans = []
res = []
backtrack(0, ans, res)
return res
39.组合总和
class Solution:
def combinationSum(self, candidates, target):
def dfs(begin, ans, res, target):
# begin存储遍历起点,避免重复遍历
if target == 0:
res.append(ans)
return
for index in range(begin, size):
residue = target - candidates[index]
if residue < 0:
break
dfs(index, ans + [candidates[index]], res, residue)
size = len(candidates) # 决定树的宽度
if size == 0:
return []
candidates.sort()
ans, res = [], []
dfs(0, ans, res, target)
return res
40. 组合总和ii
class Solution:
def combinationSum2(self, candidates, target):
def dfs(begin, ans, res, target):
# begin存储遍历起点,避免重复遍历
if target == 0:
res.append(ans)
return
for index in range(begin, size):
residue = target - candidates[index]
if residue < 0:
break
if index > begin and candidates[index] == candidates[index-1]:
continue
dfs(index + 1, ans + [candidates[index]], res, residue)
size = len(candidates) # 决定树的宽度
if size == 0:
return []
candidates.sort()
ans, res = [], []
dfs(0, ans, res, target)
return res
216. 组合总和iii
class Solution(object):
def combinationSum3(self, k, n):
"""
:type k: int
:type n: int
:rtype: List[List[int]]
"""
def backtracking(index, ans, res, target, pre):
if index == k:
if target == 0:
res.append(ans)
return
for val in range(pre+1, min(target+1, 10)):
if target - val < 0:
break
backtracking(index+1, ans + [val], res, target-val, val)
ans, res = [], []
backtracking(0, ans, res, n, 0)
return res
分割(一个字符串按一定规则有几种切割方式)
131. 分割回文串
class Solution(object):
def partition(self, s):
"""
:type s: str
:rtype: List[List[str]]
"""
def backtracking(start, ans, res):
if start == len(s):
res.append(ans)
return
for stop in range(start + 1, len(s) + 1):
if is_valid(s[start:stop]):
backtracking(stop, ans + [s[start: stop]], res)
def is_valid(tmp):
if len(tmp) == 1: return True
left, right = 0, len(tmp) - 1
while left < right:
if tmp[left] != tmp[right]: return False
left += 1
right -= 1
return True
ans, res = [], []
backtracking(0, ans, res)
return res
93. 复原IP地址
class Solution(object):
def restoreIpAddresses(self, s):
"""
:type s: str
:rtype: List[str]
"""
res = [] # 保存所有ip
ans = '' # 保存当前ip
# start:第start位的数据还未划分
# times:即将进行第times次划分
def recur(start, times, ans, res):
if times == 4:
res.append(ans)
return
for i in range(1, 4):
tmp = s[start:start+i] # 划分出的下一字段
tmp_value = int(tmp)
# 1. 划分字段值大于255
# 2. 划分字段为‘0x’形式或‘0xx’形式或‘00x’形式
# 3. 划分字段之后剩余的位数太多/太少无法划分
if tmp_value > 255 or (i > 1 and tmp[0] == '0') \
or len(s) - start - i > 3 * (3-times) \
or len(s) - start - i < 3 - times:
continue
else:
if start == 0:
recur(start+i, times+1, ans + tmp, res)
else:
recur(start + i, times + 1, ans + '.' + tmp, res)
recur(0,0,ans,res)
return res
子集(一个N个数的集合里有多少符合条件的子集)
78. 子集
class Solution(object):
def subsets(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
def backtracking(start, ans, res):
if start == len(nums):
res.append(ans)
return
backtracking(start + 1, ans + [nums[start]], res)
backtracking(start + 1, ans, res)
ans, res = [], []
backtracking(0, ans, res)
return res
90. 子集ii
class Solution(object):
def subsetsWithDup(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
def backtrack(start, ans, res):
res.append(ans)
for i in range(start, len(nums)):
if i > start and nums[i] == nums[i - 1]:
continue
backtrack(i + 1, ans + [nums[i]], res)
nums.sort()
ans, res = [], []
backtrack(0, ans, res)
return res
排列(N个数按一定规则全排列,有几种排列方式)
组合不强调元素顺序,排列强调元素顺序
46. 全排列
class Solution(object):
def permute(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
def dfs(used, ans, res):
if len(ans) == size:
res.append(ans)
return
for index in range(size):
if used[index] == 1:
continue
used[index] = 1
dfs(used, ans + [nums[index]], res)
used[index] = 0
size = len(nums)
ans, res = [], []
used = [0 for _ in range(size)]
nums.sort()
dfs(used, ans, res)
return res
# 交换
class Solution(object):
def permute(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
def backtrack(index):
if index == n:
res.append(nums[:])
return
for i in range(index, n):
nums[index], nums[i] = nums[i], nums[index]
backtrack(index + 1)
nums[index], nums[i] = nums[i], nums[index]
n = len(nums)
res = []
backtrack(0)
return res
47. 全排列ii
class Solution:
def permuteUnique(self, nums):
def dfs(used, ans, res):
if len(ans) == size:
res.append(ans)
return
for index in range(size):
if used[index] == 1:
continue
if index > 0 and nums[index] == nums[index-1] and used[index-1] == 0:
continue
used[index] = 1
dfs(used, ans + [nums[index]], res)
used[index] = 0
size = len(nums)
ans, res = [], []
used = [0 for _ in range(size)]
nums.sort()
dfs(used, ans, res)
return res
# 交换
class Solution:
def permuteUnique(self, nums):
def dfs(start):
if start == len(nums):
res.append(nums[:])
for i in range(start, len(nums)):
if i > start and nums[i] == nums[i - 1]: continue
nums[start], nums[i] = nums[i], nums[start]
dfs(start + 1)
nums[start], nums[i] = nums[i], nums[start]
res = []
dfs(0)
return res
棋盘
51. N皇后
class Solution:
def solveNQueens(self, n):
if not n: return []
board = [['.'] * n for _ in range(n)]
res = []
def isVaild(board,row, col):
#判断同一列是否冲突
for i in range(len(board)):
if board[i][col] == 'Q':
return False
# 判断左上角是否冲突
i = row -1
j = col -1
while i>=0 and j>=0:
if board[i][j] == 'Q':
return False
i -= 1
j -= 1
# 判断右上角是否冲突
i = row - 1
j = col + 1
while i>=0 and j < len(board):
if board[i][j] == 'Q':
return False
i -= 1
j += 1
return True
def backtracking(board, row, n):
# 如果走到最后一行,说明已经找到一个解
if row == n:
temp_res = []
for temp in board:
temp_str = "".join(temp)
temp_res.append(temp_str)
res.append(temp_res)
for col in range(n):
if not isVaild(board, row, col):
continue
board[row][col] = 'Q'
backtracking(board, row+1, n)
board[row][col] = '.'
backtracking(board, 0, n)
return res
37. 解数独
class Solution(object):
def solveSudoku(self, board):
"""
:type board: List[List[str]]
:rtype: None Do not return anything, modify board in-place instead.
"""
def is_valid(cur_x, cur_y, board, val):
# row
for i in range(9):
if board[i][cur_y] == str(val) and i != cur_x:
return False
# col
for j in range(9):
if board[cur_x][j] == str(val) and j != cur_y:
return False
# square
row_range = (cur_x // 3) * 3
col_range = (cur_y // 3) * 3
for i in range(row_range, row_range+3):
for j in range(col_range, col_range+3):
if board[i][j] == str(val) and i != cur_x and j != cur_y:
return False
return True
def recur(board):
for i in range(9):
for j in range(9):
if board[i][j] != '.':
continue
for k in range(1,10):
if is_valid(i, j, board, k):
board[i][j] = str(k)
if recur(board): return True
board[i][j] = '.'
return False
return True
if recur(board):
return board
else:
return
其他
491. 递增子序列
class Solution:
def findSubsequences(self, nums) :
res = []
path = []
def backtrack(nums,startIndex):
# 这里使用数组来进行去重操作
repeat = []
if len(path) >= 2:
res.append(path[:])
# 注意这里不要加return,要取树上的节点
for i in range(startIndex,len(nums)):
if nums[i] in repeat:
continue
if len(path) >= 1:
if nums[i] < path[-1]:
continue
# 记录这个元素在本层用过了,本层后面不能再用了
repeat.append(nums[i])
path.append(nums[i])
backtrack(nums,i+1)
path.pop()
backtrack(nums,0)
return res
332. 重新安排行程
class Solution(object):
def findItinerary(self, tickets):
"""
:type tickets: List[List[str]]
:rtype: List[str]
"""
# hashtable的key是出发地departure,value是目的地destination
hashtable = collections.defaultdict(list)
for val in tickets:
hashtable[val[0]].append(val[1])
def backtracking(i, start, ans):
if i == n:
return True
for index in range(len(hashtable[start])):
hashtable[start].sort()
destination = hashtable[start].pop(index)
ans.append(destination)
if backtracking(i+1, destination, ans):
return True
ans.pop(-1)
hashtable[start].append(destination)
ans = ['JFK']
n = len(tickets) + 1
backtracking(1, 'JFK', ans)
return ans