1. 二叉搜索树 (binary search tree)
对于树中的每个节点,若其左子树存在,则其左子树上每个节点的值都不大于该节点的值;若其右子树存在,则其右子树上每个节点的值都不小于该节点的值。
查询复杂度:树的高度越低,节点的查询时间复杂度越低,范围为O(logn) ~ O(n)。
2. 二叉搜索树迭代器 (binary search tree iterator) (中序遍历)
1)思路:
- 最小的第一个点,就是树最左边的点。
- 二叉树节点在中序遍历中的下一个节点:右子树的最左点 或 路径中最近一个通过左子树包含当前点的点。
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 {
Stack<TreeNode> stack;
public BSTIterator(TreeNode root) {
stack = new Stack<TreeNode>();
findMostLeft(root);
}
public int next() {
//保存当前节点,最后返回该节点
TreeNode cur = stack.peek();
//若当前节点的右子树为空,则下一个节点是栈中最近的通过左子树包含该节点的点
TreeNode node = cur;
if(node.right == null){
node = stack.pop();
while(!stack.isEmpty() && stack.peek().right == node){
node = stack.pop();
}
}else{
//若当前节点的右子树非空,则把右子树中所有左边的点放入栈中
findMostLeft(node.right);
}
return cur.val;
}
public boolean hasNext() {
if(stack.isEmpty()){
return false;
}
return true;
}
//将当前树中的左边节点都放入栈中
private void findMostLeft(TreeNode node){
while(node != null){
stack.push(node);
node = node.left;
}
}
}
/**
* 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();
*/
实现方式二 (未保存搜索到此节点的路径,每当寻找下一个节点前,都弹出当前节点。)
class BSTIterator {
//用一个栈来保存BST的待搜索节点
Stack<TreeNode> stack;
public BSTIterator(TreeNode root) {
stack = new Stack<TreeNode>();
findMostLeft(root);
}
public int next() {
//弹出当前节点
TreeNode node = stack.pop();
//若该节点有右子树,则把右子节点和右子树上所有最左边节点依次放入栈中
//若该节点无右子树,则无操作,相当于回到其父节点
if(node.right != null){
findMostLeft(node.right);
}
return node.val;
}
public boolean hasNext() {
if(stack.isEmpty()){
return false;
}
return true;
}
//把当前节点及其所有最左边节点依次放入栈中
private void findMostLeft(TreeNode node){
while(node != null){
stack.push(node);
node = node.left;
}
}
}
3. 深拷贝
1) 拷贝数组
int[] list1 = {7,8,9};
int[] list2 = new int[3];
System.arraycopy(list1,0,list2,0,list1.length);
// System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length);
/* src: 原数组
srcPos: 拷贝原数组的起始位置
dest: 目标数组
destPos: 目标数组的起始位置
length: 要copy的数组的长度
*/
list1[0] = 10;
list2[1] = 15;
System.out.println(Arrays.toString(list1) + Arrays.toString(list2));
//控制台打印出 [10,8,9][7,15,9]
2) 栈Stack的常用api
// stack的常用方法
//1.初始化
Stack<Object> stack=new Stack<>();
//2.判断是否为空
isEmpty()
//3.添加元素,push和add方法实际最终调用的是同一个方法
push(E item)
add(E item)
//4.获取栈顶值,元素不出栈(栈为空时抛异常)
peek()
//5.查看栈中是否存在obj
// 返回值为int,若存在,返回值为obj距离栈顶的位置;若不存在,返回-1
search(Object obj)
//6.移除栈顶元素,并且返回值是移除的元素
pop()
//其他方法
//7.获取stack长度
size()
//8.下标处添加
add(int index, E element)
//9.添加集合
addAll(Collection<? extends E> c)
//10.移除对象
remove(Object obj)
//11.根据下标移除对象
remove(int index)
//12.清空
clear()
4. 相关例题
LeetCode: 剑指 Offer II 055. 二叉搜索树迭代器
LintCode: 900 · 二叉搜索树中最接近的值, 901 · 二叉搜索树中最接近的值 II