关于我的 Leetcode 题目解答,代码前往 Github:https://github.com/chenxiangcyr/leetcode-answers
BST 二叉搜索树的插入
public class Solution {
/**
* @param root: The root of the binary search tree.
* @param node: insert this node into the binary search tree
* @return: The root of the new binary search tree.
*/
public TreeNode insertNode(TreeNode root, TreeNode node) {
if (root == null) {
return node;
}
if (root.val > node.val) {
root.left = insertNode(root.left, node);
} else {
root.right = insertNode(root.right, node);
}
return root;
}
}
BST 二叉搜索树的删除
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode deleteNode(TreeNode root, int key) {
if(root == null) {
return null;
}
// 递归从左子树中删除
if(root.val > key) {
root.left = deleteNode(root.left, key);
}
// 递归从右子树中删除
else if(root.val < key) {
root.right = deleteNode(root.right, key);
}
// 要删除当前节点
else {
// 如果当前节点没有左子树,则直接返回右子树
if(root.left == null) {
return root.right;
}
// 如果当前节点没有右子树,,则直接返回左子树
if(root.right == null) {
return root.left;
}
// 从右子树中找到值最小的节点,将最小值赋值到该节点
TreeNode min = findMin(root.right);
root.val = min.val;
// 递归从右子树中删除该最小值
root.right = deleteNode(root.right, min.val);
}
return root;
}
// 在树中找到值最小的节点
public TreeNode findMin(TreeNode root) {
while(root.left != null) {
root = root.left;
}
return root;
}
}
BST 二叉搜索树的搜索使用示例
LeetCode题目:285. Inorder Successor in BST 中序遍历的后继者
Given a binary search tree and a node in it, find the in-order successor of that node in the BST.
Note: If the given node has no in-order successor in the tree, return null
.
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
List list = new ArrayList<>();
public TreeNode inorderSuccessor(TreeNode root, TreeNode p) {
/*
方法1:先做中序优先遍历,再找到第一个大于p的node
*/
/*inorderTravel(root);
if(!list.contains(p)) return null;
for(TreeNode node : list) {
if(node.val > p.val) {
return node;
}
}
return null;*/
/*
方法2:使用递归
*/
/*if (root == null) return null;
if (root.val <= p.val) {
// 后继肯定在右子树里
return inorderSuccessor(root.right, p);
} else {
// 后继可能在左子树里,如果找不到,则说明是root
TreeNode left = inorderSuccessor(root.left, p);
return (left != null) ? left : root;
}*/
/*
方法3:使用迭代
*/
if (root == null) return null;
TreeNode result = null;
while(root != null) {
// 后继可能在左子树里,如果找不到,则说明是root
if(root.val > p.val) {
result = root;
root = root.left;
}
// 后继肯定在右子树里
else {
root = root.right;
}
}
return result;
}
// 中序优先遍历
public void inorderTravel(TreeNode root) {
if(root == null) return;
inorderTravel(root.left);
list.add(root);
inorderTravel(root.right);
}
}
LeetCode题目:270. Closest Binary Search Tree Value
Given a non-empty binary search tree and a target value, find the value in the BST that is closest to the target.
Note:
- Given target value is a floating point.
- You are guaranteed to have only one unique value in the BST that is closest to the target.
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
// 使用递归
public int closestValue(TreeNode root, double target) {
if(root.val == target) {
return root.val;
}
// 在左子树中查找
else if(root.val > target) {
if(root.left == null) return root.val;
int closetLeft = closestValue(root.left, target);
if(Math.abs(closetLeft - target) < Math.abs(root.val - target)) {
return closetLeft;
} else {
return root.val;
}
}
// 在右子树中查找
else {
if(root.right == null) return root.val;
int closetRight = closestValue(root.right, target);
if(Math.abs(closetRight - target) < Math.abs(root.val - target)) {
return closetRight;
} else {
return root.val;
}
}
}
// 使用迭代
public int closestValueIterative(TreeNode root, double target) {
int closestVal = root.val;
while(root != null){
//update closestVal if the current value is closer to target
closestVal = (Math.abs(target - root.val) < Math.abs(target - closestVal))? root.val : closestVal;
if(closestVal == target){ //already find the best result
return closestVal;
}
root = (root.val > target)? root.left: root.right; //binary search
}
return closestVal;
}
}
LeetCode题目:272. Closest Binary Search Tree Value II
Given a non-empty binary search tree and a target value, find k values in the BST that are closest to the target.
Note:
- Given target value is a floating point.
- You may assume k is always valid, that is: k ≤ total nodes.
- You are guaranteed to have only one unique set of k values in the BST that are closest to the target.
Follow up:
Assume that the BST is balanced, could you solve it in less than O(n) runtime (where n = total nodes)?
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List closestKValues(TreeNode root, double target, int k) {
List ret = new LinkedList<>();
// 找到target的后继结点
Stack succ = new Stack<>();
initializeSuccessorStack(root, target, succ);
// 找到target的前驱结点
Stack pred = new Stack<>();
initializePredecessorStack(root, target, pred);
if(!succ.isEmpty() && !pred.isEmpty() && succ.peek().val == pred.peek().val) {
getNextPredecessor(pred);
}
while(k > 0) {
if(succ.isEmpty()) {
ret.add(getNextPredecessor(pred));
} else if(pred.isEmpty()) {
ret.add(getNextSuccessor(succ));
} else {
double succ_diff = Math.abs((double)succ.peek().val - target);
double pred_diff = Math.abs((double)pred.peek().val - target);
if(succ_diff < pred_diff) {
ret.add(getNextSuccessor(succ));
} else {
ret.add(getNextPredecessor(pred));
}
}
k--;
}
return ret;
}
// 找到target的后继结点
private void initializeSuccessorStack(TreeNode root, double target, Stack succ) {
while(root != null) {
if(root.val == target) {
succ.push(root);
break;
} else if(root.val > target) {
succ.push(root);
root = root.left;
} else {
root = root.right;
}
}
}
// 找到target的前驱结点
private void initializePredecessorStack(TreeNode root, double target, Stack pred) {
while(root != null){
if(root.val == target){
pred.push(root);
break;
} else if(root.val > target) {
root = root.left;
} else{
pred.push(root);
root = root.right;
}
}
}
// 下一个后继结点
private int getNextSuccessor(Stack succ) {
TreeNode curr = succ.pop();
int ret = curr.val;
curr = curr.right;
while(curr != null) {
succ.push(curr);
curr = curr.left;
}
return ret;
}
// 下一个前驱结点
private int getNextPredecessor(Stack pred) {
TreeNode curr = pred.pop();
int ret = curr.val;
curr = curr.left;
while(curr != null) {
pred.push(curr);
curr = curr.right;
}
return ret;
}
}
BST 二叉搜索树的扩展使用示例
LeetCode题目:315. Count of Smaller Numbers After Self
You are given an integer array nums and you have to return a new counts array. The counts array has the property where counts[i]
is the number of smaller elements to the right of nums[i]
.
Example:
Given nums = [5, 2, 6, 1]
To the right of 5 there are 2 smaller elements (2 and 1).
To the right of 2 there is only 1 smaller element (1).
To the right of 6 there is 1 smaller element (1).
To the right of 1 there is 0 smaller element.
Return the array [2, 1, 1, 0].
class Solution {
class TreeNode {
int val;
int count; // **从左往右**,小于该val的数字的数目
int duplicates; // 该val对应的数字的重复个数
TreeNode left;
TreeNode right;
TreeNode(int val) {
this.val = val;
}
}
public List countSmaller(int[] nums) {
Integer[] result = new Integer[nums.length];
TreeNode root = null;
// 从右往左以此插入数字
for(int i = nums.length - 1; i >= 0; i--) {
root = insert(nums[i], root, result, i, 0);
}
return Arrays.asList(result);
}
// 将值为num的节点插入
public TreeNode insert(int num, TreeNode node, Integer[] result, int idx, int preSum) {
// 创建节点
if(node == null) {
node = new TreeNode(num);
node.count = 0;
node.duplicates = 1;
result[idx] = preSum;
}
// 更新节点
else if (node.val == num) {
node.duplicates++;
result[idx] = preSum + node.count;
}
// 在左子树添加
else if (node.val > num) {
node.count++;
node.left = insert(num, node.left, result, idx, preSum);
}
// 在右子树添加
else {
node.right = insert(num, node.right, result, idx, preSum + node.duplicates + node.count);
}
return node;
}
}
LeetCode题目:493. Reverse Pairs
Given an array nums
, we call (i, j)
an important reverse pair if i < j
and nums[i] > 2*nums[j]
.
You need to return the number of important reverse pairs in the given array.
Example1:
Input: [1,3,2,3,1]
Output: 2
Example2:
Input: [2,4,3,5,1]
Output: 3
class Solution {
class TreeNode {
int val;
int count; // val大于等于该val的数字的个数
TreeNode left;
TreeNode right;
TreeNode(int val) {
this.val = val;
}
}
// 将值为num的节点插入
public TreeNode insert(int num, TreeNode node) {
// 创建节点
if(node == null) {
node = new TreeNode(num);
node.count = 1;
}
// 更新节点
else if (node.val == num) {
node.count++;
}
// 在左子树添加
else if (node.val > num) {
node.left = insert(num, node.left);
}
// 在右子树添加
else {
// 新增节点比该节点大
node.count++;
node.right = insert(num, node.right);
}
return node;
}
// 查找target
public int search(long target, TreeNode node) {
if (node == null) {
return 0;
}
else if (node.val == target) {
return node.count;
}
// 在左子树查找
else if (node.val > target) {
return node.count + search(target, node.left);
}
// 在右子树查找
else {
return search(target, node.right);
}
}
public int reversePairs(int[] nums) {
int count = 0;
TreeNode head = null;
// 从左往右以此插入数字
for(int i = 0; i < nums.length; i++) {
// 先查找在之前的数字中,有多少个val大于等于nums[i] * 2l + 1的数字
count += search(nums[i] * 2l + 1, head);
// 再插入该数字
head = insert(nums[i], head);
}
return count;
}
}
LeetCode题目:173. Binary Search Tree Iterator
Implement an iterator over a binary search tree (BST). Your iterator will be initialized with the root node of a BST.
Calling next()
will return the next smallest number in the BST.
Note: next()
and hasNext()
should run in average O(1)
time and uses O(h)
memory, where h is the height of the tree.
/**
* Definition for binary tree
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class BSTIterator {
Stack stack;
public BSTIterator(TreeNode root) {
stack = new Stack();
if(root != null) {
stack.push(root);
// 将最左边的路径放入栈中
while(root.left != null) {
stack.push(root.left);
root = root.left;
}
}
}
/** @return whether we have a next smallest number */
public boolean hasNext() {
return !stack.empty();
}
/** @return the next smallest number */
public int next() {
if(stack.empty()) return 0;
TreeNode node = stack.pop();
int result = node.val;
node = node.right;
if(node != null) {
stack.push(node);
// 将最左边的路径放入栈中
while(node.left != null) {
stack.push(node.left);
node = node.left;
}
}
return result;
}
}
/**
* Your BSTIterator will be called like this:
* BSTIterator i = new BSTIterator(root);
* while (i.hasNext()) v[f()] = i.next();
*/
一点讨论
在上一个的题目中,BST中插入,删除,搜索的时间复杂度,最好情况为 O(logN)
。
但是BST 二叉搜索树不一定是平衡的,如果原数组是升序或者降序的,在插入过程中,会导致生成的BST 二叉搜索树极度不平衡,插入,删除,搜索的时间复杂度,最坏情况为 O(N)
。
为此,我们可以考虑使用平衡的二叉搜索树,例如 红黑树,AVL树,但是其实现起来比较复杂。
有没有哪种方法,既可以保证 O(logN)
的时间复杂度,又比较容易实现?请参见 树状数组Binary Indexed Tree及相关LeetCode题目