二叉搜索树
二叉搜索树 - LeetBook - 力扣(LeetCode)全球极客挚爱的技术成长平台
验证二叉搜索树
解法1
- 递归判断左小右大
- 坑点:
- 注意递归不要只比较当前节点的左右,还要注意左小都小,右大都大
- 有人给测试用例塞了个2147483647,绝了,习惯性用999999😂猛栽
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public boolean isValidBST(TreeNode root) {
return isT(root, Long.MIN_VALUE, Long.MAX_VALUE);
}
public boolean isT(TreeNode root, long min, long max) {
if (root == null) {
return true;
}
if (root.val >= max || root.val <= min) {
return false;
}
return isT(root.left, min, root.val) && isT(root.right, root.val, max);
}
}
二叉搜索树迭代器
解法1
- 直接中序遍历取出来
- 然后从list里依次判断
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class BSTIterator {
List<Integer> result;
int index = 0;
public BSTIterator(TreeNode root) {
result = new ArrayList<>();
inOrder(result, root);
}
public int next() {
return result.get(index++);
}
public boolean hasNext() {
return index < result.size();
}
public void inOrder(List<Integer> result, TreeNode node) {
if (node == null) {
return;
}
inOrder(result, node.left);
result.add(node.val);
inOrder(result, node.right);
}
}
/**
* Your BSTIterator object will be instantiated and called as such:
* BSTIterator obj = new BSTIterator(root);
* int param_1 = obj.next();
* boolean param_2 = obj.hasNext();
*/
解法2
- 迭代+栈
- 每个节点,将当前节点左节点全部入栈
- 逐个出栈
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class BSTIterator {
TreeNode node;
Deque<TreeNode> stack;
public BSTIterator(TreeNode root) {
node = root;
stack = new LinkedList<TreeNode>();
}
public int next() {
while (node != null) {
stack.push (node);
node = node.left;
}
node = stack.pop();
int result = node.val;
node = node.right;
return result;
}
public boolean hasNext() {
return node != null || !stack.isEmpty();
}
}
/**
* Your BSTIterator object will be instantiated and called as such:
* BSTIterator obj = new BSTIterator(root);
* int param_1 = obj.next();
* boolean param_2 = obj.hasNext();
*/
二叉搜索树中的搜索
解法1
简单递归
- 等于 -> 返回
- 小于 -> 左递归
- 大于 -> 右递归
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public TreeNode searchBST(TreeNode root, int val) {
if (root == null) {
return null;
}
if (root.val == val) {
return root;
} else if (root.val > val) {
return searchBST(root.left, val);
} else {
return searchBST(root.right, val);
}
}
}
二叉搜索树中的插入操作
解法1
- 递归
- 小则往左递归
- 大则往右递归
- 碰到null插入
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public TreeNode insertIntoBST(TreeNode root, int val) {
if (root == null) {
root = new TreeNode(val);
return root;
}
insert(root, val);
return root;
}
public void insert(TreeNode node, int val) {
if (val > node.val) {
if (node.right == null) {
node.right = new TreeNode(val);
return;
}
node = node.right;
} else {
if (node.left == null) {
node.left = new TreeNode(val);
return;
}
node = node.left;
}
insert(node, val);
}
}
删除二叉搜索树中的节点
解法1
- 递归
- 如果相等
- 左树为空,则直接把右树接上
- 右树为空,则直接把左树接上
- 两边都不为空(二选一)
- 左树取最大值替掉当前节点
- 右树取最小值替掉当前节点
- 返回root
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public TreeNode deleteNode(TreeNode root, int key) {
if (root == null) {
return null;
}
if (root.val == key) {
if (root.left == null) {
return root.right;
}
if (root.right == null) {
return root.left;
}
TreeNode temp = root.left;
while (temp.right != null) {
temp = temp.right;
}
temp.right = root.right;
return root.left;
} else if (root.val < key) {
root.right = deleteNode(root.right, key);
} else {
root.left = deleteNode(root.left, key);
}
return root;
}
}
数据流中的第K大元素
解法1
topK问题,重点
优先队列
class KthLargest {
Queue<Integer> queue;
int kkkk;
public KthLargest(int k, int[] nums) {
kkkk = k;
queue = new PriorityQueue<Integer>();
for (int num : nums) {
queue.add(num);
}
}
public int add(int val) {
queue.offer(val);
while (queue.size() > kkkk) {
queue.poll();
}
return queue.peek();
}
}
/**
* Your KthLargest object will be instantiated and called as such:
* KthLargest obj = new KthLargest(k, nums);
* int param_1 = obj.add(val);
*/
二叉搜索树的最近公共祖先
解法1
直接复用二叉树的最近公共祖先
- 递归
- 递归自己,如果碰到要找的节点,就返回
- 判断左为空就都在右边
- 判断右为空就都在左边
- 否则就一边一个,返回当前节点
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root == null || root == p || root == q) {
return root;
}
TreeNode left = lowestCommonAncestor(root.left, p, q);
TreeNode right = lowestCommonAncestor(root.right, p, q);
if (left == null) {
return right;
}
if (right == null) {
return left;
}
return root;
}
}
解法2
- 递归
- 先换一下位置,确保p小q大
- 如果root和p,q中的一个相等,则return
- 如果p小于root,q大于root,则return
- 如果root大于q,则向左递归
- 如果root小于q,则向右递归
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (p.val > q.val) {
return lowestCommonAncestor(root, q, p);
}
if (root == p || root == q || root.val > p.val && root.val < q.val) {
return root;
} else if (root.val > q.val) {
return lowestCommonAncestor(root.left, p, q);
} else {
return lowestCommonAncestor(root.right, p, q);
}
}
}
存在重复元素Ⅲ
解法1
【宫水三叶】一题双解:「滑动窗口 & 二分」&「桶排序」解法 - 存在重复元素 III - 力扣(LeetCode)
class Solution {
long size;
public boolean containsNearbyAlmostDuplicate(int[] nums, int indexDiff, int valueDiff) {
int n = nums.length;
Map<Long, Long> map = new HashMap<>();
size = valueDiff + 1L;
for (int i = 0; i < n; i++) {
long u = nums[i] * 1L;
long idx = getIdx(u);
if (map.containsKey(idx)) {
return true;
}
long l = idx - 1, r = idx + 1;
if (map.containsKey(l) && u - map.get(l) <= valueDiff) {
return true;
}
if (map.containsKey(r) && map.get(r) - u <= valueDiff) {
return true;
}
map.put(idx, u);
if (i >= indexDiff) {
map.remove(getIdx(nums[i - indexDiff] * 1L));
}
}
return false;
}
public long getIdx(long u) {
return u >= 0 ? u / size : ((u + 1) / size) - 1;
}
}
平衡二叉树
解法1
- 自顶向下递归
- 递归
- 如果root为空返回true
- 如果左右树的深度差大于1,返回false
- 返回判断左右子树是否为平衡二叉树
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public boolean isBalanced(TreeNode root) {
if (root == null) {
return true;
}
int left = deep(root.left);
int right = deep(root.right);
if (Math.abs(left - right) > 1) {
return false;
}
return isBalanced(root.left) && isBalanced(root.right);
}
public int deep(TreeNode root) {
if (root == null) {
return 0;
}
return Math.max(deep(root.left), deep(root.right)) + 1;
}
}
解法2
- 自底向上递归,解决方法1中deep方法重复调用的问题,先判断左右子树是否平衡,在判断当前节点是否平衡
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public boolean isBalanced(TreeNode root) {
return deep(root) >= 0;
}
public int deep(TreeNode root) {
if (root == null) {
return 0;
}
int left = deep(root.left);
int right = deep(root.right);
if (left == -1 || right == -1 || Math.abs(left - right) > 1) {
return -1;
}
return Math.max(left, right) + 1;
}
}
将有序数组转换为二叉搜索树
解法1
- 有序数组,每次取中点,即为当前节点
- 左右节点分别从中间切开的左右两个数组取中点
- 依次递归
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public TreeNode sortedArrayToBST(int[] nums) {
if (nums.length == 0) {
return null;
}
return createTree(nums, 0, nums.length - 1);
}
public TreeNode createTree(int[] nums, int start, int end) {
if (start > end) {
return null;
}
int mid = start + (end - start) / 2;
TreeNode root = new TreeNode(nums[mid]);
root.left = createTree(nums, start, mid - 1);
root.right = createTree(nums, mid + 1, end);
return root;
}
}