一、扁平化方法,预处理
1.递归方式
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class BSTIterator { //扁平化法,将二叉搜索树的中序遍历序列存储在一位数组中,之后按顺序查找
private:
vector<int> ans; //一位数组
int i; //记录当前遍历到第几个结点
void def_ans(TreeNode* p,vector<int> &ans){ //中序遍历函数,给数组赋值
if(p == NULL) return;
def_ans(p->left,ans);
ans.push_back(p->val);
def_ans(p->right,ans);
}
public:
BSTIterator(TreeNode* root):i(0) { //构造函数,初始化i,赋值数组
def_ans(root,ans);
}
int next() { //按顺序返回数组值
return ans[i++];
}
bool hasNext() { //判断是否遍历完
if(i < ans.size()) return true;
else return false;
}
};
/**
* Your BSTIterator object will be instantiated and called as such:
* BSTIterator* obj = new BSTIterator(root);
* int param_1 = obj->next();
* bool param_2 = obj->hasNext();
*/
2.非递归方式(栈实现)
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class BSTIterator { //扁平化法,将二叉搜索树的中序遍历序列存储在一位数组中,之后按顺序查找
private:
vector<int> ans; //一位数组
int i; //记录当前遍历到第几个结点
public:
BSTIterator(TreeNode* root):i(0) { //构造函数,初始化i,用非递归方式(栈实现)中序遍历赋值数组
stack<TreeNode*> stk;
TreeNode *p = root;
while(p || !stk.empty()) { //中序遍历
if(p) {
stk.push(p);
p = p->left;
}
else {
p = stk.top();
stk.pop();
ans.push_back(p->val);
p = p->right;
}
}
}
int next() { //按顺序返回数组值
return ans[i++];
}
bool hasNext() { //判断是否遍历完
if(i < ans.size()) return true;
else return false;
}
};
/**
* Your BSTIterator object will be instantiated and called as such:
* BSTIterator* obj = new BSTIterator(root);
* int param_1 = obj->next();
* bool param_2 = obj->hasNext();
*/
预处理的时间复杂度O(N),N为结点数;next()和hasNext()时间复杂度都是O(1)。
需要一个一维数组,空间复杂度O(N)。
二、单调栈迭代法
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class BSTIterator { //单调栈迭代法,每次调用next()实时维护一次栈,每次只维护到中序遍历下一个结点为止,故只需要O(h)的空间,可以达到本题的进阶要求
private:
stack<TreeNode*> stk; //单调栈,保存中序遍历序列
TreeNode* p;
public:
BSTIterator(TreeNode* root):p(root) {}
int next() { //维护一次栈,从当前结点遍历到其最左下孩子结点(即最小结点),将最后的结点返回,并转向遍历右子树
while(p) {
stk.push(p);
p = p->left;
}
p = stk.top();
stk.pop();
int temp = p->val;
p = p->right;
return temp;
}
bool hasNext() {
if(p || !stk.empty()) return true; //指针未空或栈未空代表还没遍历完
else return false;
}
};
/**
* Your BSTIterator object will be instantiated and called as such:
* BSTIterator* obj = new BSTIterator(root);
* int param_1 = obj->next();
* bool param_2 = obj->hasNext();
*/
本方法主要是针对本题的进阶要求,减少额外空间。
本方法与扁平化法中非递归方法的本质是一样的,区别是中序遍历是迭代分段实时进行的,只需要O(h)的空间复杂度,h是树的深度。
next()虽在左子树较长时需要O(h)的时间,但在总的中序遍历过程中总共需要O(N)的时间,故均摊时间复杂度还是O(1)。
以上,达到进阶要求。