举例让抽象问题具体化如果没有思路,那就尝试手推几个例子吧。题 27:二叉树的镜像题目:请完成一个函数,输入一课二叉树,请函数输出它的镜像。解法: 镜像也就意味着每一个子树的左右节点都得互换,所以自然可以想到可以使用递归交换每个节点的左右子树就好了;顺手也写了个非递归版。# -*- coding:utf-8 -*- class TreeNode: def __init__(self, x): self.val = x self.left = None self.right = None class Solution: # 返回镜像树的根节点 def Mirror(self, root): if root is None: return stack = [] stack.append(root) while stack: temp = stack.pop() if temp.left is not None or temp.right is not None: temp.left, temp.right = temp.right, temp.left if temp.left is not None: stack.append(temp.left) if temp.right is not None: stack.append(temp.right) def Mirror_recur(self, root): """递归版""" if root is None: return if root.left or root.right: root.left, root.right = root.right, root.left self.Mirror_recur(root.left) self.Mirror_recur(root.right) def mirror(self, root1, root2): """检测两棵二叉树是不是镜像树 Args: root1 (TreeNode): 二叉树头结点 root2 (TreeNode): 二叉树头结点 Returns: bool: 是否为镜像树 """ if root1 is None and root2 is None: return True if root1 is None or root2 is None: return False if root1.val != root2.val: return False return self.mirror(root1.left, root2.right) and self.mirror(root1.right, root2.left) def main(): root = TreeNode(8) root.left = TreeNode(6) root.right = TreeNode(10) root.left.left = TreeNode(5) root.left.right = TreeNode(7) root.right.left = TreeNode(9) root.right.right = TreeNode(11) # 镜像树 root1 = TreeNode(8) root1.left = TreeNode(6) root1.right = TreeNode(10) root1.left.left = TreeNode(5) root1.left.right = TreeNode(7) root1.right.left = TreeNode(9) root1.right.right = TreeNode(11) ex = Solution() ex.Mirror(root) print(ex.mirror(root1, root)) if __name__ == '__main__': main() 题 28:对称的二叉树题目:请实现一个函数,用来判断一课二叉树是不是对称的。如果一个二叉树和它的镜像一样,那么他就是对称的。解法:题意说的很清楚,可以通过判断二叉树和它的镜像是否相等来判断二叉树是否对象,或者换一种说法,检测二叉树和它自己是否是镜像才。利用树的遍历,前序中左右,我们再写一个自定义序中右左,那么对于对称树,这两个遍历序是一样的,可以利用这个来确定是否是对称树。# -*- coding:utf-8 -*- class TreeNode: def __init__(self, x): self.val = x self.left = None self.right = None class Solution: def is_symmetry_tree(self, root1, root2): """检测两棵二叉树是不是镜像树 Args: root1 (TreeNode): 二叉树头结点 root2 (TreeNode): 二叉树头结点 Returns: bool: 是否为镜像树 """ if root1 is None and root2 is None: return True if root1 is None or root2 is None: return False if root1.val != root2.val: return False return self.is_symmetry_tree(root1.left, root2.right) and \ self.is_symmetry_tree(root1.right, root2.left) def main(): root = TreeNode(8) root.left = TreeNode(6) root.right = TreeNode(6) root.left.left = TreeNode(5) root.left.right = TreeNode(7) root.right.left = TreeNode(7) root.right.right = TreeNode(5) ex = Solution() print(ex.is_symmetry_tree(root, root)) if __name__ == '__main__': main() 题 29:顺时针打印矩阵题目:输入一个矩阵,按照从外向内以顺时针一次打印出每一个数字。解法:这个题主要是确定每次的打印范围,然后规范化打印之后再处理特殊情况:# -*- coding:utf-8 -*- class Solution: """matrix 类型为二维列表,需要返回列表""" def printMatrix(self, matrix): res = [] row_length = len(matrix) col_length = len(matrix[0]) if row_length == 0 or col_length == 0: return res i = j = 0 m = row_length - 1 n = col_length - 1 while i < m and j < n: for _ in range(j, n): res.append(matrix[i][_]) for _ in range(i, m): res.append(matrix[_][n]) for _ in range(n, j, -1): res.append(matrix[m][_]) for _ in range(m, i, -1): res.append(matrix[_][j]) i += 1 j += 1 m -= 1 n -= 1 if i == m == j == n: res.append(matrix[i][j]) elif i == m: for _ in range(j, n+1): res.append(matrix[i][_]) elif j == n: for _ in range(i, m+1): res.append(matrix[_][n]) return res 举例让抽象问题具体化如果规律不能一眼看出来,那就试着用具体例子模拟过程吧。不要钻牛角尖,因为没有用。题 30:包含 min 函数的栈使用辅助栈,辅助栈与主栈同步增长,辅助栈中放入已压入元素的最小值;辅助栈与主栈同步弹出;# -*- coding:utf-8 -*- class Solution: def __init__(self): self.stack = [] self.stack_min = [] self.min_value = None def push(self, node): if not self.stack: self.min_value = node else: self.min_value = min(self.min_value, node) self.stack.append(node) self.stack_min.append(self.min_value) def pop(self): self.stack_min.pop() return self.stack.pop() def top(self): return self.stack[-1] def min(self): return self.stack_min[-1] 题 31:栈的压入、弹出序列解法:如果要判断一个序列是不是栈的弹出序列,那么把压入序列真正的压入一遍就知道了。此题分析如下:设立一个辅助栈和两个变量用作标志,一个指向弹出序列中的待弹出元素,一个指向压入序列中还未压入栈的元素,两个变量初始值都为 0;如果待弹出元素和栈顶元素不相同,那么就去待压入元素中寻找和待弹出元素相等的值,将其压入栈;如果待弹出元素和栈顶元素相同,那么弹出栈顶,待弹出元素往后继续,重复这个过程直到变成条件 2,再重复条件 2;在 3 中如果找不到相等元素,那么就说明弹出序列有问题。# -*- coding:utf-8 -*- class Solution: def IsPopOrder(self, pushV, popV): if len(pushV) != len(popV): return False stack = [] cur_push = 0 cur_pop = 0 while stack or cur_push < len(pushV): # cur_pop 与栈顶相同,则弹出,cur_pop + 1 if stack and stack[-1] == popV[cur_pop]: stack.pop() cur_pop += 1 else: # cur_pop 与栈顶不同,那么开始压栈,直到找到相等值 while cur_push < len(pushV) and pushV[cur_push] != popV[cur_pop]: stack.append(pushV[cur_push]) cur_push += 1 if cur_push < len(pushV): stack.append(pushV[cur_push]) cur_push += 1 # 去除长度不等之外的唯一错误情况:找不到相等值压栈 else: return False return True 题 32:从上往下打印二叉树题目一:不分行打印题目二:分行打印从上到下打印二叉树的每个节点,同一层的节点按照从左到右的顺序打印,代码实现的为分行打印。解法:层次遍历,利用队列解,剩下的大家就都知道了。class TreeNode(): def __init__(self, val): self.val = val self.left = None self.right = None class Solution(): def print_tree_with_level(self, root): if root is None: return None qu = [] qu.append(root) count = 0 while qu: to_be_print = len(qu) while to_be_print > 0: temp = qu.pop(0) print(temp.val, end=' ') if temp.left: qu.append(temp.left) if temp.right: qu.append(temp.right) to_be_print -= 1 count += 1 print('第%d 层、n' % count) def main(): root = TreeNode(1) root.left = TreeNode(2) root.right = TreeNode(3) root.left.left = TreeNode(4) root.left.right = TreeNode(5) root.right.left = TreeNode(6) root.right.right = TreeNode(7) ex = Solution() ex.print_tree_with_level(root) if __name__ == '__main__': main() 题目三:之字形打印二叉树题目:请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,如此反复。# -*- coding=utf-8 -*- class TreeNode(): def __init__(self, val): self.val = val self.left = None self.right = None class Solution(): """分层之字形打印二叉树 """ def Print(self, pRoot): if pRoot is None: return [] s1, s2, res = [], [], [] s1.append(pRoot) while s1 or s2: if s1: cur_level_res = [] while s1: item = s1.pop() cur_level_res.append(item.val) if item.left: s2.append(item.left) if item.right: s2.append(item.right) res.append(cur_level_res) if s2: cur_level_res = [] while s2: item = s2.pop() cur_level_res.append(item.val) if item.right: s1.append(item.right) if item.left: s1.append(item.left) res.append(cur_level_res) return res def main(): root = TreeNode(1) root.left = TreeNode(2) root.right = TreeNode(3) root.left.left = TreeNode(4) root.left.right = TreeNode(5) root.right.left = TreeNode(6) root.right.right = TreeNode(7) ex = Solution() print(ex.Print(root)) if __name__ == "__main__": main() 题 33:二叉搜索树的后序遍历序列题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。假设数组中没有相同元素。解法:# -*- coding:utf-8 -*- class Solution: def VerifySquenceOfBST(self, sequence): length = len(sequence) if length <= 0: return False root = sequence[-1] for i in range(length): if sequence[i] > root: break j = i for j in range(i, length-1): if sequence[j] < root: return False left = True if i > 0: left = self.VerifySquenceOfBST(sequence[:i]) right = True if i < length - 1: right = self.VerifySquenceOfBST(sequence[i:-1]) return left and right 题 34:二叉树中和为某一值的路径题目:输入一棵二叉树和一个整数,打印出二叉树中节点值得和为输入整数的所有路径。从树的根节点开始往下一直到叶节点所经过的节点形成一条路径。# -*- coding:utf-8 -*- class TreeNode: def __init__(self, x): self.val = x self.left = None self.right = None class Solution: def FindPath(self, root, expectNumber): """找到二叉树中和为某个值的路径 Args: root (TreeNode): 二叉树根节点 expectNumber (int): 目标和 Returns: list: 二维列表,内部每个列表表示找到的路径 """ if root is None: return [] res = [] def find_main(root, path, cur_sum): cur_sum += root.val path.append(root) is_leaf = True if root.left is None and root.right is None else False if cur_sum == expectNumber and is_leaf: one_path = [] for item in path: one_path.append(item.val) res.append(one_path) if cur_sum < expectNumber: if root.left is not None: find_main(root.left, path, cur_sum) if root.right is not None: find_main(root.right, path, cur_sum) path.pop() find_main(root, [], 0) return res 分解让复杂问题简单化将大问题分解成小问题——怎样将大问题分解成小问题?无他,多练,就脑熟了。题 35:复杂链表的复制题目:请实现函数复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 sibling 指针指向链表中的任意节点或者 None。# -*- coding:utf-8 -*- class RandomListNode: def __init__(self, x): self.label = x self.next = None self.random = None class Solution: def Clone(self, pHead): """返回克隆的复杂链表的头结点 Args: pHead (RandomListNode): 复杂链表头部 Returns: RanddomListNode: 复制链表头部 """ if pHead is None: return None buf_dict = {} copy_head = RandomListNode(pHead.label) p, copy_p = pHead, copy_head while p.next is not None: copy_p.next = RandomListNode(p.next.label) p = p.next copy_p = copy_p.next buf_dict[p] = copy_p p, copy_p = pHead, copy_head while p is not None: if p.random is not None: copy_p.random = buf_dict[p.random] p = p.next copy_p = copy_p.next return copy_head 题 36:二叉搜索树与双向链表输入一个二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新节点,只能调整树中节点指针的指向。# -*- coding:utf-8 -*- class TreeNode: def __init__(self, x): self.val = x self.left = None self.right = None class Solution: def Convert(self, pRootOfTree): """将二叉搜索树与双向链表 Args: pRootOfTree (TreeNode): 二叉树根节点 Returns: TreeNode: 双向链表头部 """ if pRootOfTree is None: return pRootOfTree if pRootOfTree.left is None and pRootOfTree.right is None: return pRootOfTree def mid_order(root, res): if root is None: return res mid_order(root.right, res) res.append(root) mid_order(root.left, res) return res pre_res = mid_order(pRootOfTree, []) pre_res = pre_res[::-1] head = pre_res[0] head.left = None head.right = pre_res[1] if len(pre_res) > 2: for i in range(1, len(pre_res)-1): temp = pre_res[i] temp.left = pre_res[i-1] temp.right = pre_res[i+1] pre_res[-1].right = None pre_res[-1].left = pre_res[-2] return head 题 37:序列化二叉树题目:请实现两个函数,分别用来序列化和反序列化二叉树# -*- coding:utf-8 -*- class TreeNode: def __init__(self, x): self.val = x self.left = None self.right = None class Solution: def Serialize(self, root): """前序序列化二叉树 Args: root (TreeNo): 二叉树根节点 Returns: str: 序列化字符串 """ if root is None: return '#_' res = '%d_' % root.val res += self.Serialize(root.left) res += self.Serialize(root.right) return res def Deserialize(self, s): """根据字符串反序列化由 Serialize 函数序列化的二叉树 Args: s (str): 序列化的字符串 Returns: TreeNode: 反序列化之后二叉树头结点 """ s = s.split('_')[:-1] def inside(s): head = s.pop(0) print(head) if head == '#': return None head = TreeNode(int(head)) head.left = inside(s) head.right = inside(s) return head return inside(s) 题 38:字符串的排列解法:全排列问题,可以用递归做。递归做的越多越发现有时候递归不是很好写。暂定以后的递归套路为分析最后情况,制定 basecase 必须要给递归返回有利条件。# -*- coding:utf-8 -*- class Solution: def Permutation(self, ss): if ss is None or len(ss) < 2: return ss ss = list(ss) res = set({}) self.permut(ss, 0, res) return sorted(list(res)) def permut(self, ss, begin, res): if begin == len(ss) - 1: res.add(''.join(ss)) return cur = begin for cur in range(begin, len(ss)): self.swap(ss, begin, cur) # 交换 self.permut(ss, begin+1, res) self.swap(ss, begin, cur) # 复位 def swap(self, ss, i, j): ss[i], ss[j] = ss[j], ss[i]