电话号码组合
思路:遍历每层的输入,当层次“溢出”回溯
class Solution(object):
def letterCombinations(self, digits):
"""
:type digits: str
:rtype: List[str]
"""
if len(digits)==0:
return []
dic = {str(i+1):[chr(ord('a')+j) for j in range(i*3-3,i*3)] for i in range(1,6)}
dic['7'] = ['p','q','r','s']
dic['8'] = ['t','u','v']
dic['9'] = ['w','x','y','z']
ans = []
def dfs(inx,s):
if inx==len(digits):
ans.append(s[:])
return
for c in dic[digits[inx]]:
dfs(inx+1,s+c)
dfs(0,"")
return ans
括号生成
思路:左括号肯定位于右括号之前,所以必然先左后右。当左右括号都输出完,那就阔以存一波了。感觉回溯还真不好说思路,画个递归树就清楚了。
class Solution(object):
def generateParenthesis(self, n):
"""
:type n: int
:rtype: List[str]
"""
ans = []
def dfs(left,right,s):
if left==right and n==left:
ans.append(s)
return
if left>n or left<right or right>n:
return
dfs(left+1,right,s+'(')
dfs(left,right+1,s+')')
dfs(0,0,"")
return ans
全排列
思路:因为无法重复使用。需要一个标识位去存读某一位是否用过
class Solution(object):
def permute(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
flag = [False]*len(nums)
ans = []
def dfs(s):
if len(nums)==len(s):
ans.append(s[:])
return
for i in range(len(flag)):
if flag[i]:
continue
flag[i] = True
s.append(nums[i])
dfs(s)
s.pop()
flag[i] = False
dfs([])
return ans
子集
就是组合的感觉,就是每一层的起点调整为下一位。来一种情况存一个。
class Solution:
def subsets(self, nums):
res = []
n = len(nums)
def helper(i, tmp):
res.append(tmp)
for j in range(i, n):
helper(j + 1,tmp + [nums[j]])
helper(0, [])
return res
单次搜索
这就是标准的深搜了
class Solution(object):
def exist(self, board, word):
"""
:type board: List[List[str]]
:type word: str
:rtype: bool
"""
def dfs(x,y,inx):
if inx==len(word):
return True
if x>=len(board) or x<0 or y>=len(board[0]) or y<0 or board[x][y] != word[inx] or b[x][y]:
return False
b[x][y] = True
flag = dfs(x+1,y,inx+1) or dfs(x,y+1,inx+1) or dfs(x-1,y,inx+1) or dfs(x,y-1,inx+1)
if not flag:
b[x][y] =False;
return flag
if board=="" and word=="":
return True
if board=="" or word=="":
return False
for i in range(len(board)):
for j in range(len(board[0])):
if board[i][j]==word[0]:
b = [[False for _ in range(len(board[0]))] for _ in range(len(board))]
flag = dfs(i,j,0)
if flag:
return True
return False
颜色分类
使用双指针呗(或者说三指针),最后2肯定放于尾,0肯定放于头,遇到0就尝试往前放,如果之前0指针原本指向非1,则下次仍然需要再判断一遍,2也同理。
class Solution(object):
def sortColors(self, nums):
"""
:type nums: List[int]
:rtype: None Do not return anything, modify nums in-place instead.
"""
inx0 = 0
inx2 = len(nums)-1
i =0
while i<=inx2:
if nums[i] == 0:
nums[i],nums[inx0] = nums[inx0],nums[i]
inx0 += 1
i += 1
elif nums[i]==2:
nums[i],nums[inx2] = nums[inx2],nums[i]
inx2 -= 1
else:
i += 1
前 K 个高频元素
肯定用字典存一波数字的数量,然后用长度位k的最小堆存储,然后输出堆就行了。
class Solution(object):
class heap:
__slots__ = ['k','h','size']
def __init__(self,k):
self.h = []
self.k = k
self.size = 0
def add(self,val,si):
if self.size<self.k:
self.__flow(val,si)
else:
self.__sink(val,si)
def __sink(self,val,si):
if si<=self.h[0][1]:
return
self.h[0] = [val,si]
inx = 0
while (inx<<1)+1<len(self.h):
inx_next = (inx<<1)+1
if inx_next+1<len(self.h) and self.h[inx_next+1][1]<self.h[inx_next][1]:
inx_next += 1
if self.h[inx][1]>self.h[inx_next][1]:
self.h[inx_next],self.h[inx] = self.h[inx],self.h[inx_next]
inx = inx_next
else:
return
def __flow(self,val,si):
self.h.append([val,si])
self.size += 1
inx = len(self.h)-1
while inx>0 and self.h[inx-1>>1][1]>=self.h[inx][1]:
inx_n = inx-1>>1
if inx_n<0:
# print self.h
return
self.h[inx],self.h[inx_n] = self.h[inx_n],self.h[inx]
inx = inx_n
# print self.h
def topKFrequent(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: List[int]
"""
di = {}
for i in nums:
if i in di.keys():
di[i] += 1
else:
di[i] = 1
h = self.heap(k)
# print(di)
for i in di.keys():
h.add(i,di[i])
return [i[0] for i in h.h]