BFS
- java:用hashmap/hashset来去重
- python:dict/set来去重
分治法 divide & conquer
- 将大规模问题拆分为若干个小规模同类型问题去处理
- 再把子问题分为更小的问题,直到最后子问题可以简单求解
- 最后将子问题的解合并就是原问题的解
?通常用递归方法来解决
搜索
?宽度优先搜索 ?深度优先搜索(DFS) = 回溯 ?遍历法:可用递归或迭代(非递归) ?分治法:可用递归或迭代(非递归) 注:递归和非递归是算法的一种实现方式而不是算法
递归三要素: 1.递归的定义 2.递归的拆解 3.递归的出口
Binary search tree要点 定义:左子树节点的值<根节点的值,右子树节点的值>=根节点的值 中序遍历:对二叉查找树使用中序遍历,则会发现中序遍历的list列表是有序的(不下降的顺序,有些相邻点可能相等) ?若二叉树中序遍历不是“不下降”序列,则一定不是BST ?若二叉树的中序遍历是不下降,也未必是BST,如[1,1,1]
平衡二叉树(balanced binary tree) ?平衡二叉树可以是一棵空树 ?左右子树高度差不大于1 ?子树也必须是一棵平衡二叉树
二叉树的问题大部分可以用分治法的算法思想,DFS的算法和递归的程序设计方式去进行求解。 递归就是当多重for循环层数不确定时候,一个更优雅实现多重循环的方式。
import string
from collections import deque
"""
combination
"""
class solution1():
def __init__(self):
self.KEYBOARD = {
'2': 'abc',
'3': 'def',
'4': 'ghi',
'5': 'jkl',
'6': 'mno',
'7': 'pqrs',
'8': 'tuv',
'9': 'wxyz'}
def letterCombination(self, digits):
if not digits:
return []
combinations = []
self.dfs(digits, 0, [], combinations)
return combinations
def dfs(self, digits, index, combination, combinations):
if index == len(digits):
combinations.append(''.join(combination))
return
for letter in self.KEYBOARD[digits[index]]:
combination.append(letter)
self.dfs(digits, index + 1, combination, combinations)
combination.pop()
class solution2():
def kSumII(self, A, k, target):
A.sort()
subsets = []
self.dfs(A, 0, k, target, [], subsets)
return subsets
def dfs(self, A, index, k, target, subset, subsets):
if k == 0 and target == 0:
subsets.append(list(subset))
return
if k == 0 or target <= 0:
return
for i in range(index, len(A)):
subset.append(A[i])
self.dfs(A, index + 1, k - 1, target - A[i], subset, subsets)
subset.pop()
class solution3():
def combinationSum(self, candidates, target):
if not candidates:
return []
results = []
unique_sorted_numbers = sorted(list(set(candidates)))
self.dfs(unique_sorted_numbers, 0, [], target, results)
return results
def dfs(self, nums, index, current_result, remain_target, results):
if remain_target == 0:
return results.append(list(current_result))
for i in range(index, len(nums)):
if remain_target < nums[i]:
break
current_result.append(nums[i])
self.dfs(nums, i, current_result, remain_target - nums[i], results)
current_result.pop()
class solution4():
def stringPermutation(self, str):
if str is None:
return
chars = sorted(list(str))
visited = [False] * len(chars)
permutations = []
self.dfs(chars, visited, [], permutations)
return permutations
def dfs(self, chars, visited, permutation, permutations):
if len(permutation) == len(chars):
permutations.append(''.join(permutation))
return
for i in range(len(chars)):
if visited[i]:
continue
if i >0 and chars[i-1] == chars[i] and not visited[i-1]:
continue
visited[i] = True
permutation.append(chars[i])
self.dfs(chars, visited, permutation, permutations)
permutation.pop()
visited[i] = False
DIRECTIONS = [(0,-1),(0,1),(-1,0),(1,0)]
class solution5():
def wordSearchII(self, board, words):
if board is None or len(board) == 0:
return []
word_set = set(words)
prefix_set = set()
for word in words:
for i in range(len(word)):
prefix_set.add(word[:i+1])
result_set = set()
for i in range(len(board)):
for j in range(len(board[0])):
self.search(
board,
i,
j,
board[i][j],
word_set,
prefix_set,
set([(i,j)]),
result_set,
)
return list(result_set)
def search(self, board, x, y, word, word_set, prefix_set, visited, result_set):
if word not in prefix_set:
return
if word in word_set:
result_set.add(word)
for delta_x, delta_y in DIRECTIONS:
x_ = x + delta_x
y_ = y + delta_y
if not self.inside(board, x_, y_) or (x_, y_) in visited:
continue
visited.add((x_,y_))
self.search(
board,
x_,
y_,
word + board[x_][y_],
word_set,
prefix_set,
visited,
result_set
)
visited.remove((x_,y_))
def inside(self, board, x, y):
return 0<=x<len(board) and 0<=y<len(board[0])
'''
start = 'hit'
end = 'zog'
dict = ['hot','dot','dog','lot','log']
'''
class solution6():
def findLadders(self, start, end, d):
d.add(start)
d.add(end)
distance = {}
fromToDict = {}
for s in d:
fromToDict[s] = []
self.bfs(start, fromToDict, distance, d)
results = []
self.dfs(start, end, distance, d, [], results, fromToDict, distance[end])
return results
def bfs(self, start, fromToDict, distance, d):
distance[start] = 0
queue = deque([start])
while queue:
curr_word = queue.popleft()
for next_word in self.get_next_words(curr_word, d):
if (next_word not in distance or distance[next_word] == distance[curr_word] + 1):
fromToDict[curr_word].append(next_word)
if next_word not in distance:
distance[next_word] = distance[curr_word] + 1
queue.append(next_word)
def dfs(self, curr_word, target, distance, d, path, results, fromToDict, min_len):
if len(path) == min_len + 1:
return
path.append(curr_word)
if curr_word == target:
results.append(list(path))
else:
for nextWord in fromToDict[curr_word]:
self.dfs(nextWord, target, distance, d, path, results, fromToDict, min_len)
path.pop()
def get_next_words(self, word, d):
words = []
for i in range(len(word)):
for c in string.ascii_lowercase:
if (word[i] == c):
continue
next_word = word[:i] + c +word[i+1:]
if next_word in d:
words.append(next_word)
return words
if __name__ == '__main__':
test = solution1()
com = test.letterCombination(['2','3'])
A = [1,3,4,6]
test = solution2()
sub = test.kSumII(A, 3, 8)
candidates = [2,3,7]
test = solution3()
res = test.combinationSum(candidates, 7)
chars ='abb'
test = solution4()
per = test.stringPermutation(chars)
board = ['doaf','agai','dcan']
words = ['dog','dad','dgdg','can','again']
DIRECTIONS = [(0, -1), (0, 1), (-1, 0), (1, 0)]
test = solution5()
res = test.wordSearchII(board, words)
start = 'hit'
end = 'zog'
dict = set(['hot', 'dot', 'dog', 'lot', 'log'])
test = solution6()
res = test.findLadders(start, end, dict)
print(res)
|