一:二叉树的右视图
1. 深度优先搜索
通过另一个深度栈来维护每一层唯一的可见值,这个值为后添加的右节点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 class Solution {public : vector<int > rightSideView (TreeNode* root) { unordered_map<int , int > hashMap; stack<TreeNode*> stk; stack<int > stkDepth; int maxDepth = 0 ; stk.push (root); stkDepth.push (1 ); while (stk.empty () == false ) { TreeNode* node = stk.top (); stk.pop (); int depth = stkDepth.top (); stkDepth.pop (); if (node != nullptr ) { maxDepth = max (maxDepth, depth); if (hashMap.count (depth) == false ) hashMap[depth] = node->val; stk.push (node->left); stk.push (node->right); stkDepth.push (depth + 1 ); stkDepth.push (depth + 1 ); } } vector<int > result; for (int i = 1 ; i <= maxDepth; ++i) result.emplace_back (hashMap[i]); return result; } };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class Solution { public List<Integer> rightSideView (TreeNode root) { Map<Integer, Integer> hashMap = new HashMap <>(); Deque<TreeNode> stk = new LinkedList <>(); Deque<Integer> stkDepth = new LinkedList <>(); int maxDepth = 0 ; stk.push(root); stkDepth.push(1 ); while (stk.isEmpty() == false ) { TreeNode node = stk.pop(); int depth = stkDepth.pop(); if (node != null ) { maxDepth = Math.max(maxDepth, depth); if (hashMap.containsKey(depth) == false ) hashMap.put(depth, node.val); stk.push(node.left); stk.push(node.right); stkDepth.push(depth + 1 ); stkDepth.push(depth + 1 ); } } List<Integer> result = new ArrayList <>(); for (int i = 1 ; i <= maxDepth; ++i) result.add(hashMap.get(i)); return result; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class Solution : def rightSideView (self, root: Optional [TreeNode] ) -> List [int ]: hashMap = dict () maxDepth = 0 stack = [(root, 1 )] while stack: node, depth = stack.pop() if (node != None ): maxDepth = max (maxDepth, depth) if (depth not in hashMap): hashMap[depth] = node.val stack.append((node.left, depth + 1 )) stack.append((node.right, depth + 1 )) result = [] for i in range (1 , maxDepth + 1 ): result.append(hashMap[i]) return result
2. 广度优先搜索
类似于深度,这里使用队列执行先进先出,因此从左节点开始向右遍历
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 class Solution {public : vector<int > rightSideView (TreeNode* root) { unordered_map<int , int > hashMap; queue<TreeNode*> stk; queue<int > stkDepth; int maxDepth = 0 ; stk.push (root); stkDepth.push (1 ); while (stk.empty () == false ) { TreeNode* node = stk.front (); stk.pop (); int depth = stkDepth.front (); stkDepth.pop (); if (node != nullptr ) { maxDepth = max (maxDepth, depth); hashMap[depth] = node->val; stk.push (node->left); stk.push (node->right); stkDepth.push (depth + 1 ); stkDepth.push (depth + 1 ); } } vector<int > result; for (int i = 1 ; i <= maxDepth; ++i) result.emplace_back (hashMap[i]); return result; } };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class Solution { public List<Integer> rightSideView (TreeNode root) { Map<Integer, Integer> hashMap = new HashMap <>(); Queue<TreeNode> stk = new LinkedList <>(); Queue<Integer> stkDepth = new LinkedList <>(); int maxDepth = 0 ; stk.add(root); stkDepth.add(1 ); while (stk.isEmpty() == false ) { TreeNode node = stk.remove(); int depth = stkDepth.remove(); if (node != null ) { maxDepth = Math.max(maxDepth, depth); hashMap.put(depth, node.val); stk.add(node.left); stk.add(node.right); stkDepth.add(depth + 1 ); stkDepth.add(depth + 1 ); } } List<Integer> result = new ArrayList <>(); for (int i = 1 ; i <= maxDepth; ++i) result.add(hashMap.get(i)); return result; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class Solution : def rightSideView (self, root: Optional [TreeNode] ) -> List [int ]: hashMap = dict () maxDepth = 0 queue = deque([(root, 1 )]) while queue: node, depth = queue.popleft() if (node != None ): maxDepth = max (maxDepth, depth) hashMap[depth] = node.val queue.append((node.left, depth + 1 )) queue.append((node.right, depth + 1 )) result = [] for i in range (1 , maxDepth + 1 ): result.append(hashMap[i]) return result
二:二叉树展开为链表
1. 前序遍历
前序遍历得到所有节点的数组,然后逐一构建
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class Solution {public : void flatten (TreeNode* root) { vector<TreeNode*> listTree; PreOrder (root, listTree); for (int i = 1 ; i < listTree.size (); ++i) { TreeNode* pre = listTree[i - 1 ]; TreeNode* cur = listTree[i]; pre->right = cur; pre->left = nullptr ; } } void PreOrder (TreeNode* node, vector<TreeNode*>& listTree) { if (node != nullptr ) { listTree.emplace_back (node); PreOrder (node->left, listTree); PreOrder (node->right, listTree); } } };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class Solution { public void flatten (TreeNode root) { List<TreeNode> listTree = new ArrayList <>(); PreOrder(root, listTree); for (int i = 1 ; i < listTree.size(); ++i) { TreeNode pre = listTree.get(i - 1 ); TreeNode cur = listTree.get(i); pre.right = cur; pre.left = null ; } } public void PreOrder (TreeNode node, List<TreeNode> listTree) { if (node != null ) { listTree.add(node); PreOrder(node.left, listTree); PreOrder(node.right, listTree); } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 class Solution : def flatten (self, root: Optional [TreeNode] ) -> None : listTree = list () self .PreOrder(root, listTree) for i in range (1 , len (listTree)): pre = listTree[i - 1 ] cur = listTree[i] pre.right = cur pre.left = None def PreOrder (self, node, listTree ): if (node != None ): listTree.append(node) self .PreOrder(node.left, listTree) self .PreOrder(node.right, listTree)
2. 前序遍历和展开同步进行
不使用额外数组,使用栈来使遍历和创建新链表同时进行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class Solution {public : void flatten (TreeNode* root) { if (root == nullptr ) return ; stack<TreeNode*> stk; stk.push (root); TreeNode* pre = nullptr ; while (stk.empty () == false ) { TreeNode* cur = stk.top (); stk.pop (); if (pre != nullptr ) { pre->left = nullptr ; pre->right = cur; } if (cur->right != nullptr ) stk.push (cur->right); if (cur->left != nullptr ) stk.push (cur->left); pre = cur; } } };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class Solution { public void flatten (TreeNode root) { if (root == null ) return ; Deque<TreeNode> stk = new LinkedList <>(); stk.push(root); TreeNode pre = null ; while (stk.isEmpty() == false ) { TreeNode cur = stk.pop(); if (pre != null ) { pre.left = null ; pre.right = cur; } if (cur.right != null ) stk.push(cur.right); if (cur.left != null ) stk.push(cur.left); pre = cur; } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 class Solution : def flatten (self, root: Optional [TreeNode] ) -> None : if (root == None ): return stk = [root] pre = None while (stk): cur = stk.pop() if (pre != None ): pre.left = None pre.right = cur if (cur.right != None ): stk.append(cur.right) if (cur.left != None ): stk.append(cur.left) pre = cur
3. 寻找前驱节点
这个方法有点类似于二叉树的中序遍历 中的Morris方法,通过将左子树最后的右节点指向当前节点的右节点,从而建立连接关系,相当于更改了当前链表的结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 */ class Solution {public : void flatten (TreeNode* root) { if (root == nullptr ) return ; auto cur = root; while (cur != nullptr ) { if (cur->left != nullptr ) { auto node = cur->left; auto next = node; while (node->right != nullptr ) node = node->right; node->right = cur->right; cur->left = nullptr ; cur->right = next; } cur = cur->right; } } };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class Solution { public void flatten (TreeNode root) { if (root == null ) return ; TreeNode cur = root; while (cur != null ) { if (cur.left != null ) { TreeNode node = cur.left; TreeNode next = node; while (node.right != null ) node = node.right; node.right = cur.right; cur.left = null ; cur.right = next; } cur = cur.right; } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 class Solution : def flatten (self, root: Optional [TreeNode] ) -> None : if (root == None ): return cur = root while (cur != None ): if (cur.left != None ): node = cur.left next = node while (node.right != None ): node = node.right node.right = cur.right cur.left = None cur.right = next cur = cur.right
三:从前序与中序遍历序列构造二叉树
1. 递归
通过前序遍历找到中序遍历的根节点,然后左右划分依次递归,需要先处理左边,因为先序遍历根节点之后是左子树
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class Solution {private : unordered_map<int , int > index; public : TreeNode* myBuildTree (const vector<int >& preorder, const vector<int >& inorder, int preorder_left, int preorder_right, int inorder_left, int inorder_right) { if (preorder_left > preorder_right) { return nullptr ; } int preorder_root = preorder_left; int inorder_root = index[preorder[preorder_root]]; TreeNode* root = new TreeNode (preorder[preorder_root]); int size_left_subtree = inorder_root - inorder_left; root->left = myBuildTree (preorder, inorder, preorder_left + 1 , preorder_left + size_left_subtree, inorder_left, inorder_root - 1 ); root->right = myBuildTree (preorder, inorder, preorder_left + size_left_subtree + 1 , preorder_right, inorder_root + 1 , inorder_right); return root; } TreeNode* buildTree (vector<int >& preorder, vector<int >& inorder) { int n = preorder.size (); for (int i = 0 ; i < n; ++i) { index[inorder[i]] = i; } return myBuildTree (preorder, inorder, 0 , n - 1 , 0 , n - 1 ); } };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class Solution { private Map<Integer, Integer> indexMap; public TreeNode myBuildTree (int [] preorder, int [] inorder, int preorder_left, int preorder_right, int inorder_left, int inorder_right) { if (preorder_left > preorder_right) { return null ; } int preorder_root = preorder_left; int inorder_root = indexMap.get(preorder[preorder_root]); TreeNode root = new TreeNode (preorder[preorder_root]); int size_left_subtree = inorder_root - inorder_left; root.left = myBuildTree(preorder, inorder, preorder_left + 1 , preorder_left + size_left_subtree, inorder_left, inorder_root - 1 ); root.right = myBuildTree(preorder, inorder, preorder_left + size_left_subtree + 1 , preorder_right, inorder_root + 1 , inorder_right); return root; } public TreeNode buildTree (int [] preorder, int [] inorder) { int n = preorder.length; indexMap = new HashMap <Integer, Integer>(); for (int i = 0 ; i < n; i++) { indexMap.put(inorder[i], i); } return myBuildTree(preorder, inorder, 0 , n - 1 , 0 , n - 1 ); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class Solution : def buildTree (self, preorder: List [int ], inorder: List [int ] ) -> TreeNode: def myBuildTree (preorder_left: int , preorder_right: int , inorder_left: int , inorder_right: int ): if preorder_left > preorder_right: return None preorder_root = preorder_left inorder_root = index[preorder[preorder_root]] root = TreeNode(preorder[preorder_root]) size_left_subtree = inorder_root - inorder_left root.left = myBuildTree(preorder_left + 1 , preorder_left + size_left_subtree, inorder_left, inorder_root - 1 ) root.right = myBuildTree(preorder_left + size_left_subtree + 1 , preorder_right, inorder_root + 1 , inorder_right) return root n = len (preorder) index = {element: i for i, element in enumerate (inorder)} return myBuildTree(0 , n - 1 , 0 , n - 1 )
2. 迭代
这个解法巧妙的利用了先序和中序的特点,先序从根节点先到达最后一个左节点,中序则从最后一个左节点开始,当先序的某个节点和中序的第一个相等意味着当前节点的左子树结束,此时用栈来维护没有处理右子树的节点即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class Solution {public : TreeNode* buildTree (vector<int >& preorder, vector<int >& inorder) { if (!preorder.size ()) { return nullptr ; } TreeNode* root = new TreeNode (preorder[0 ]); stack<TreeNode*> stk; stk.push (root); int inorderIndex = 0 ; for (int i = 1 ; i < preorder.size (); ++i) { int preorderVal = preorder[i]; TreeNode* node = stk.top (); if (node->val != inorder[inorderIndex]) { node->left = new TreeNode (preorderVal); stk.push (node->left); } else { while (!stk.empty () && stk.top ()->val == inorder[inorderIndex]) { node = stk.top (); stk.pop (); ++inorderIndex; } node->right = new TreeNode (preorderVal); stk.push (node->right); } } return root; } };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class Solution { public TreeNode buildTree (int [] preorder, int [] inorder) { if (preorder == null || preorder.length == 0 ) { return null ; } TreeNode root = new TreeNode (preorder[0 ]); Deque<TreeNode> stack = new LinkedList <TreeNode>(); stack.push(root); int inorderIndex = 0 ; for (int i = 1 ; i < preorder.length; i++) { int preorderVal = preorder[i]; TreeNode node = stack.peek(); if (node.val != inorder[inorderIndex]) { node.left = new TreeNode (preorderVal); stack.push(node.left); } else { while (!stack.isEmpty() && stack.peek().val == inorder[inorderIndex]) { node = stack.pop(); inorderIndex++; } node.right = new TreeNode (preorderVal); stack.push(node.right); } } return root; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class Solution : def buildTree (self, preorder: List [int ], inorder: List [int ] ) -> TreeNode: if not preorder: return None root = TreeNode(preorder[0 ]) stack = [root] inorderIndex = 0 for i in range (1 , len (preorder)): preorderVal = preorder[i] node = stack[-1 ] if node.val != inorder[inorderIndex]: node.left = TreeNode(preorderVal) stack.append(node.left) else : while stack and stack[-1 ].val == inorder[inorderIndex]: node = stack.pop() inorderIndex += 1 node.right = TreeNode(preorderVal) stack.append(node.right) return root
四:路径总和 III
1. 深度优先搜索
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class Solution {public : int rootSum (TreeNode* root, int targetSum) { if (!root) { return 0 ; } int ret = 0 ; if (root->val == targetSum) { ret++; } ret += rootSum (root->left, targetSum - root->val); ret += rootSum (root->right, targetSum - root->val); return ret; } int pathSum (TreeNode* root, int targetSum) { if (!root) { return 0 ; } int ret = rootSum (root, targetSum); ret += pathSum (root->left, targetSum); ret += pathSum (root->right, targetSum); return ret; } };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class Solution { public int pathSum (TreeNode root, long targetSum) { if (root == null ) { return 0 ; } int ret = rootSum(root, targetSum); ret += pathSum(root.left, targetSum); ret += pathSum(root.right, targetSum); return ret; } public int rootSum (TreeNode root, long targetSum) { int ret = 0 ; if (root == null ) { return 0 ; } int val = root.val; if (val == targetSum) { ret++; } ret += rootSum(root.left, targetSum - val); ret += rootSum(root.right, targetSum - val); return ret; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Solution : def pathSum (self, root: TreeNode, targetSum: int ) -> int : def rootSum (root, targetSum ): if root is None : return 0 ret = 0 if root.val == targetSum: ret += 1 ret += rootSum(root.left, targetSum - root.val) ret += rootSum(root.right, targetSum - root.val) return ret if root is None : return 0 ret = rootSum(root, targetSum) ret += self .pathSum(root.left, targetSum) ret += self .pathSum(root.right, targetSum) return ret
2. 前缀和
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class Solution {public : unordered_map<long long , int > prefix; int dfs (TreeNode *root, long long curr, int targetSum) { if (!root) { return 0 ; } int ret = 0 ; curr += root->val; if (prefix.count (curr - targetSum)) { ret = prefix[curr - targetSum]; } prefix[curr]++; ret += dfs (root->left, curr, targetSum); ret += dfs (root->right, curr, targetSum); prefix[curr]--; return ret; } int pathSum (TreeNode* root, int targetSum) { prefix[0 ] = 1 ; return dfs (root, 0 , targetSum); } };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Solution { public int pathSum (TreeNode root, int targetSum) { Map<Long, Integer> prefix = new HashMap <Long, Integer>(); prefix.put(0L , 1 ); return dfs(root, prefix, 0 , targetSum); } public int dfs (TreeNode root, Map<Long, Integer> prefix, long curr, int targetSum) { if (root == null ) { return 0 ; } int ret = 0 ; curr += root.val; ret = prefix.getOrDefault(curr - targetSum, 0 ); prefix.put(curr, prefix.getOrDefault(curr, 0 ) + 1 ); ret += dfs(root.left, prefix, curr, targetSum); ret += dfs(root.right, prefix, curr, targetSum); prefix.put(curr, prefix.getOrDefault(curr, 0 ) - 1 ); return ret; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class Solution : def pathSum (self, root: TreeNode, targetSum: int ) -> int : prefix = collections.defaultdict(int ) prefix[0 ] = 1 def dfs (root, curr ): if not root: return 0 ret = 0 curr += root.val ret += prefix[curr - targetSum] prefix[curr] += 1 ret += dfs(root.left, curr) ret += dfs(root.right, curr) prefix[curr] -= 1 return ret return dfs(root, 0 )
五:二叉树的最近公共祖先
1. 递归
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class Solution {public : TreeNode* ans; bool dfs (TreeNode* root, TreeNode* p, TreeNode* q) { if (root == nullptr ) return false ; bool lson = dfs (root->left, p, q); bool rson = dfs (root->right, p, q); if ((lson && rson) || ((root->val == p->val || root->val == q->val) && (lson || rson))) { ans = root; } return lson || rson || (root->val == p->val || root->val == q->val); } TreeNode* lowestCommonAncestor (TreeNode* root, TreeNode* p, TreeNode* q) { dfs (root, p, q); return ans; } };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class Solution { private TreeNode ans; public Solution () { this .ans = null ; } private boolean dfs (TreeNode root, TreeNode p, TreeNode q) { if (root == null ) return false ; boolean lson = dfs(root.left, p, q); boolean rson = dfs(root.right, p, q); if ((lson && rson) || ((root.val == p.val || root.val == q.val) && (lson || rson))) { ans = root; } return lson || rson || (root.val == p.val || root.val == q.val); } public TreeNode lowestCommonAncestor (TreeNode root, TreeNode p, TreeNode q) { this .dfs(root, p, q); return this .ans; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 class Solution : def __init__ (self ): self .ans = None def dfs (self, root: 'TreeNode' , p: 'TreeNode' , q: 'TreeNode' ) -> bool : if not root: return False lson = self .dfs(root.left, p, q) rson = self .dfs(root.right, p, q) if (lson and rson) or ((root.val == p.val or root.val == q.val) and (lson or rson)): self .ans = root return lson or rson or (root.val == p.val or root.val == q.val) def lowestCommonAncestor (self, root: 'TreeNode' , p: 'TreeNode' , q: 'TreeNode' ) -> 'TreeNode' : self .dfs(root, p, q) return self .ans
2. 存储父节点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class Solution {public : unordered_map<int , TreeNode*> fa; unordered_map<int , bool > vis; void dfs (TreeNode* root) { if (root->left != nullptr ) { fa[root->left->val] = root; dfs (root->left); } if (root->right != nullptr ) { fa[root->right->val] = root; dfs (root->right); } } TreeNode* lowestCommonAncestor (TreeNode* root, TreeNode* p, TreeNode* q) { fa[root->val] = nullptr ; dfs (root); while (p != nullptr ) { vis[p->val] = true ; p = fa[p->val]; } while (q != nullptr ) { if (vis[q->val]) return q; q = fa[q->val]; } return nullptr ; } };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class Solution { Map<Integer, TreeNode> parent = new HashMap <Integer, TreeNode>(); Set<Integer> visited = new HashSet <Integer>(); public void dfs (TreeNode root) { if (root.left != null ) { parent.put(root.left.val, root); dfs(root.left); } if (root.right != null ) { parent.put(root.right.val, root); dfs(root.right); } } public TreeNode lowestCommonAncestor (TreeNode root, TreeNode p, TreeNode q) { dfs(root); while (p != null ) { visited.add(p.val); p = parent.get(p.val); } while (q != null ) { if (visited.contains(q.val)) { return q; } q = parent.get(q.val); } return null ; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class Solution : def __init__ (self ): self .fa = {} self .visited = set () def dfs (self, root: 'TreeNode' ): if root.left: self .fa[root.left.val] = root self .dfs(root.left) if root.right: self .fa[root.right.val] = root self .dfs(root.right) def lowestCommonAncestor (self, root: 'TreeNode' , p: 'TreeNode' , q: 'TreeNode' ) -> 'TreeNode' : self .fa[root.val] = None self .dfs(root) while p: self .visited.add(p.val) p = self .fa.get(p.val) while q: if q.val in self .visited: return q q = self .fa.get(q.val) return None