235.二叉搜索树的最近公共祖先
文章:28. 二叉搜索树的最近公共祖先
题目:235. 二叉搜索树的最近公共祖先
【思路】
二叉搜索树:找到一个节点的值在两边的子树、在p和q之间(一定是最近的公共祖先!)
会出现乘积溢出的情况:
1 2 3
| if((root.val - p.val) * (root.val - q.val) <= 0){ return root; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class Solution { public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { while(true){ if(root.val >p.val && root.val > q.val){ return lowestCommonAncestor(root.left,p,q); } else if(root.val < p.val && root.val <q.val){ return lowestCommonAncestor(root.right,p,q); }else{ break; } } return root; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode { if root == nil { return root } for{ if root.Val > p.Val && root.Val > q.Val{ root = root.Left } if root.Val <p.Val && root.Val <q.Val{ root = root.Right } if (root.Val - p.Val) * (root.Val - q.Val) <=0{ return root } } return root }
|
701.二叉搜索树中的插入操作
文章:29. 二叉搜索树中的插入操作
题目:701. 二叉搜索树中的插入操作
【思路】
在不调整二叉树的结构的前提下,找到空节点插入元素即可。因此我们需要对二叉搜索树进行遍历操作(递归)。
递归三部曲
确定递归函数参数以及返回值
确定终止条件
确定单层递归的逻辑
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class Solution { public TreeNode insertIntoBST(TreeNode root, int val) { if(root == null){ TreeNode node = new TreeNode(val); return node; } if(root.val > val){ root.left = insertIntoBST(root.left,val); } if(root.val < val){ root.right = insertIntoBST(root.right,val); } return root; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| func insertIntoBST(root *TreeNode, val int) *TreeNode { if root == nil{ node := &TreeNode{Val: val} return node } if root.Val > val{ root.Left = insertIntoBST(root.Left,val) } if root.Val < val{ root.Right = insertIntoBST(root.Right,val) } return root }
|
450.删除二叉搜索树中的节点
文章:30. 删除二叉搜索树中的节点
题目:调整二叉树的结构最难!| LeetCode:450.删除二叉搜索树中的节点_哔哩哔哩_bilibili
【思路】
不可避免的需要去调整二叉树的结构。
第一种情况:没找到要删除的节点
第二种情况:要删除的节点是叶子节点
第三种情况:要删除的节点左子树不空,右子树空\左子树空,右子树不空
第四种情况:要删除的节点左不为空右不为空
回溯:解决单层处理逻辑
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
| class Solution { public TreeNode deleteNode(TreeNode root, int key) { return traversal(root,key); } public TreeNode traversal(TreeNode root , int key){ if (root == null)return null; if(root.val == key){ if ( root.left == null && root.right == null){ return null; }else if (root.left != null &&root.right == null){ return root.left; }else if (root.left == null &&root.right != null){ return root.right; }else{ TreeNode cur = root.right ; while(cur.left!= null)cur = cur.left; cur.left = root.left; return root.right; } } if(key < root.val) root.left = traversal(root.left,key); if(key > root.val) root.right = traversal(root.right,key); 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 28
| func deleteNode(root *TreeNode, key int) *TreeNode { return traversal(root,key) } func traversal(root *TreeNode,key int)*TreeNode{ if root == nil{ return nil } if root.Val == key{ if root.Left == nil && root.Right == nil{ return nil }else if root.Left != nil && root.Right == nil{ return root.Left }else if root.Left == nil && root.Right != nil{ return root.Right }else{ cur := root.Right for cur.Left != nil{ cur = cur.Left } cur.Left = root.Left return root.Right } } root.Left = traversal(root.Left , key) root.Right = traversal(root.Right,key) return root }
|
【算法总结】
- 二叉搜索树的公共祖先:使用递归,保证数值为一正一负,则说明数值在当前节点的左右子树!(但是存在数值溢出的风险)我们可以选择break直接返回(条件要严苛一点)。
- 二叉搜索树中的插入操作:使用递归,二叉搜索树的特性使我们直接在空节点处插入数值即可,不涉及对树结构的修改。
- 删除二叉搜索树中的节点:使用递归,需要注意区分三种情况。第四种改变结构的情况需要注意,新建一个node节点来操作二叉树与key相等的节点的right节点,将与key相等的节点包含的树都加入进right节点的左节点的left节点(左节点要为空),重新构建好该节点后返回root.right节点(与key相等的节点需要删除)。