每一轮遍历的节点都与根节点路径长度相同。设 di 表示第 i 个节点与根节点的路径长度,可以推导出结论:对于先遍历的节点 i 与后遍历的节点 j,有 di<=dj。 利用上述结论,可以求解最短路径 最优解 问题:第一次遍历到目的节点,其所经过的路径为最短路径,如果继续遍历,之后再遍历到目的节点,所经过的路径就不是最短路径。
defgenerateParenthesis(self, n): res = [] defdfs(left, right, string): if right < left: return if left == 0and right == 0: res.append(string) if left > 0: dfs(left-1, right, string + '(') if right > 0: dfs(left, right-1, string + ')') dfs(n, n, '') return res
defcombinationSum(self, candidates, target): res = [] defdfs(cans, tar, start, arr): if tar < 0: return if tar == 0: res.append(arr) return for i in range(start, len(cans)): if cans[i] <= tar: dfs(cans, tar-cans[i], i, arr+[cans[i]]) dfs(candidates, target, 0, []) return res
defcombinationSum2(self, candidates, target): res = [] defdfs(cans, tar, start, arr): if tar < 0: return if tar == 0and arr notin res: res.append(arr) return for i in range(len(cans)): if cans[i] <= tar: dfs(cans[i+1:], tar-cans[i], i+1, arr+[cans[i]]) candidates = sorted(candidates) dfs(candidates, target, 0, []) return res
defcombinationSum3(self, k, n): res = [] nums = [i for i in range(1, 10)] defdfs(nums, target, arr): if target < 0: return if target == 0and len(arr) == k and sorted(nums) notin res: res.append(arr) return for i in range(len(nums)): dfs(nums[i+1:], target-nums[i], arr + [nums[i]]) dfs(nums, n, []) return res
defpermute(self, nums): res = [] defdfs(n, arr): ifnot n: res.append(arr) return for i in range(len(n)): dfs(n[:i]+n[i+1:], arr+[n[i]]) dfs(nums, []) return res
备注:不要用 pop(),会改变原数组,导致最后数组为空,直接 n[:i]+n[i+1:] 表示删除第 i 个数
直接在上一题的基础上添加条件 if not n and arr not in res,会超时。 为了提交效率,可以先对 nums 排序,那么相同的元素会在一起,在遍历时,如果遇到相同的元素,其结果会和之前的元素相同,就不要重复递归了。由于添加了元素是否重复的判断,那么得到的 arr 便也不会重复了,因此 if not n 后面不用再接着判断 arr 是否存在于 res 中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
defpermuteUnique(self, nums):= res = [] defdfs(n, arr): ifnot n: res.append(arr) return for i in range(len(n)): if i > 0and n[i] == n[i-1]: continue dfs(n[:i]+n[i+1:], arr+[n[i]]) nums.sort() dfs(nums, []) return res
The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two queens attack each other Given an integer n, return all distinct solutions to the n-queens puzzle. Each solution contains a distinct board configuration of the n-queens’ placement, where ‘Q’ and ‘.’ both indicate a queen and an empty space respectively.
defsolveNQueens(self, n): """ :type n: int :rtype: List[List[str]] """ defcheck(i, j):# 判断第 i 个皇后能否放在第 j 列,由于是一行一行的放置,因此也就是能否放在第 i 行的第 j 列 for k in range(i): # 与前 i-1 行进行比较 if board[k] == j or abs(k-i) == abs(board[k]-j): # 判断是否会和第 k 行的皇后在同一列或同一对角线 returnFalse returnTrue defdfs(col, arr): if col == n: res.append(arr) return for j in range(n): # 一行行的放皇后,每行的每列开始尝试 if check(col, j): # 如果第 col 行的 第 j 列可以放置 board[col] = j s = '.' * n # 初始化需要打印的结果 dfs(col+1, arr+[s[:j]+'Q'+s[j+1:]]) res = [] board = [-1for i in range(n)] # 初始化棋盘 dfs(0, []) # 从第 0 行开始摆放棋子 return res
deftotalNQueens(self, n): defcheck(i, j): for k in range(i): if board[k] == j or abs(board[k]-j) == abs(k-i): returnFalse returnTrue defdfs(col): if col == n: self.res += 1 return for j in range(n): if check(col, j): board[col] = j dfs(col+1) self.res = 0 board = [-1for i in range(n)] dfs(0) return self.res
defcombine(self, n, k): res = [] nums = [i for i in range(1, n+1)] defdfs(nums, k, arr): if len(arr) == k and sorted(arr) notin res: res.append(arr) return for i in range(len(nums)): dfs(nums[i+1:], k, arr+[nums[i]]) dfs(nums, k, []) return res
defsubsets(self, nums): res = [] defdfs(nums, arr): res.append(arr) for i in range(len(nums)): dfs(nums[i+1:], arr+[nums[i]]) dfs(sorted(nums), []) return res
Given a string containing only digits, restore it by returning all possible valid IP address combinations. Input: “25525511135” Output: [“255.255.11.135”, “255.255.111.35”]
思路:合法 IP 地址分为四部分,每个部分的长度为 1-3 位, 大小为 0-255 之间
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
defrestoreIpAddresses(self, s): if len(s) > 12: return [] res = [] defdfs(s, ip): ifnot s and len(ip) == 4: res.append('.'.join(ip)) return for i in range(1, 4): if i <= len(s): number = int(s[:i]) # 此处为了防止出现两位数以上,0 开头的情况。 if number <= 255and str(number) == s[:i]: dfs(s[i:], ip+[s[:i]]) dfs(s, []) return res
defpartition(self, s): self.is_palindorm = lambda s : s == s[::-1] res = [] defdfs(s, palindorm): ifnot s: res.append(palindorm) return for i in range(len(s)): if self.is_palindorm(s[:i+1]): dfs(s[i+1:], palindorm + [s[:i+1]]) dfs(s, []) return res
defladderLength(self, beginWord, endWord, wordList): if endWord notin wordList ornot wordList: return0 wordSet = set(wordList) alphas = set(''.join(wordSet)) queue = [[beginWord, 1]] while queue: word, length = queue.pop(0) if word == endWord: return length for i in range(len(word)): for c in alphas: newWord = word[:i] + c + word[i+1:] if newWord in wordSet and newWord != word: wordSet.remove(newWord) queue.append([newWord, length+1]) return0
defsolve(self, board): ifnot board: return n = len(board) m = len(board[0]) defdfs(i, j): if i < 0or i >= n or j < 0or j >= m or board[i][j] != 'O': return board[i][j] = 'D' dfs(i+1, j) dfs(i-1, j) dfs(i, j+1) dfs(i, j-1) for j in range(m): # 第0行和最后一行 if board[0][j] == 'O': dfs(0, j) if board[n-1][j] == 'O': dfs(n-1, j) for i in range(n): # 第0列和最后一列 if board[i][0] == 'O': dfs(i, 0) if board[i][m-1] == 'O': dfs(i, m-1) for i in range(n): for j in range(m): if board[i][j] == 'D': board[i][j] = 'O' else: board[i][j] = 'X'
defnumIslands(self, grid): ifnot grid: return0 cnt = 0 n = len(grid) m = len(grid[0]) defdfs(i, j): if i < 0or i >= n or j < 0or j >= m or grid[i][j] != '1': return grid[i][j] = '0' dfs(i-1, j) dfs(i+1, j) dfs(i, j+1) dfs(i, j-1) for i in range(n): for j in range(m): if grid[i][j] == '1': dfs(i, j) cnt += 1 return cnt