class Solution {
public:
//根节点的取值范围是minv~maxv。long long防int溢出。
bool dfs(TreeNode* root, long long minv, long long maxv){
if(!root) return true;
if(root->val < minv || root->val > maxv) return false;
//左树根节点严格小于root->val。取值minv~root->val-1
//右树根节点严格大于root->val。取值root->val+1~maxv
return dfs(root->left, minv, root->val-1ll) && dfs(root->right, root->val+1ll, maxv);
}
bool isValidBST(TreeNode* root) {
return dfs(root, INT_MIN, INT_MAX);
}
};
class Solution {
public:
bool dfs(TreeNode* l, TreeNode* r){
//l 和 r同时为真,不执行。同时为假,返回真
if(!l || !r) return !l && !r;
//递归的两节点值相等
//左树的左树值等于右树的右树,左树的右树值等于右树的左树
return l->val==r->val && dfs(l->left, r->right) && dfs(l->right, r->left);
}
bool isSymmetric(TreeNode* root) {
if(!root) return true;
return dfs(root->left, root->right);
}
};
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> ans;
stack<TreeNode*> stk;
TreeNode* p = root;
while(stk.size() || p){
while(p){
stk.push(p);
p = p->left;
}
p = stk.top(); stk.pop();
ans.push_back(p->val);
p = p->right;
}
return ans;
}
};
class Solution {
public:
vector<int> pre, in;
//此题说明元素各不相同,pos存放中序序列中每个值的下标
unordered_map<int, int> pos;
//用pre的[pl, pr], in的[il, ir]进行建树
TreeNode* dfs(int pl, int pr, int il, int ir) {
//r为根节点值,k为根节点在中序序列中的位置
int r = pre[pl], k = pos[r];
auto root = new TreeNode(r);
//中序序列分为两部分左子树【il,k-1】,右子树【k+1,ir】
//前序序列也被分成两部分,且长度与中序的两部分相等
//若存在左树
if(il <= k-1) root->left = dfs(pl+1, pl+1+k-1-il, il, k-1);
//若存在右树
if(k+1 <= ir) root->right = dfs(pl+k-il+1, pr, k+1, ir);
return root;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
if(preorder.empty() || inorder.empty()) return NULL;
pre = preorder, in = inorder;
for(int i = 0; i < in.size(); i ++)
pos[in[i]] = i;
return dfs(0, pre.size()-1, 0, in.size()-1);\
}
};
可通过在每遍历完一层在队列后面添加一个空指针的方式代表一层的结束。一定要添加条件判断if(q.size()) q.push(NULL);最后一层遍历完后不添加空指针。
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> ans;
vector<int> path;
if(!root) return ans;
queue<TreeNode*> q;
q.push(root);
q.push(NULL);
while(q.size()){
auto t = q.front(); q.pop();
if(t) {
path.push_back(t->val);
if(t->left) q.push(t->left);
if(t->right) q.push(t->right);
}
else{
ans.push_back(path);
path.clear();
if(q.size()) q.push(NULL);
}
}
return ans;
}
};
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
// 若root子树中含有p(q),则返回p(q)
// 若一边有p,令一边有q,root是最深公共祖先
// 若一边有p和q, 一边没有,则返回的是最深公共祖先
if(!root || root==q || root==p) return root;
auto l = lowestCommonAncestor(root->left, p, q);
auto r = lowestCommonAncestor(root->right, p, q);
if(l && r) return root;
else if(l) return l;
else return r;
}
};
左树和右树的高度和即为经过此根节点的最大长度
class Solution {
public:
int ans;
int getHeight(TreeNode* root){
if(!root) return 0;
int l = getHeight(root->left);
int r = getHeight(root->right);
//左树和右树的高度和即为经过此根节点的最大长度
ans = max(ans, l + r);
return max(l, r) + 1 ;
}
int diameterOfBinaryTree(TreeNode* root) {
getHeight(root);
return ans;
}
};
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int ans = INT_MIN;
//dfs求从root这点出发到它的任意孩子(向下走)的最大路径和
int dfs(TreeNode* root){
if(!root) return 0;
int l = dfs(root->left), r = dfs(root->right);
l = l > 0? l : 0, r = r > 0? r : 0;
//枚举每个节点的最大路径和
//以此点为最高点的最大路径必然是res和左树、右树都走的最大值
ans = max(ans, l + r + root->val);
//一个点向下走的最大路径应是以下三种情况之一
//往左走、往右走、不走
return max(l, r) + root->val;
}
int maxPathSum(TreeNode* root) {
dfs(root);
return ans;
}
};
next() 和 hasNext() 操作的平均时间复杂度是 O(1),并使用 O(h) 内存,其中 h 是树的高度。可考虑用栈模拟中序遍历来做。栈最大是树的高度。
class BSTIterator {
public:
stack<TreeNode*> stk;
BSTIterator(TreeNode* root) {
//初始化
while(root){
stk.push(root);
root = root->left;
}
}
/** @return the next smallest number */
int next() {
auto p = stk.top(); stk.pop();
int res = p->val;
//对右子树中序遍历
p = p->right;
while(p){
stk.push(p);
p = p->left;
}
return res;
}
/** @return whether we have a next smallest number */
bool hasNext() {
return stk.size();
}
};
class Solution {
public:
TreeNode* inorderSuccessor(TreeNode* p) {
//如存在右子树,返回右子树的最左节点
if(p->right) {
p = p->right;
//左孩子存在时,才向左遍历
while(p->left) p = p->left;
return p;
}
//如果存在父亲,且p是其父亲的右子树,p->father的右子树遍历完成。
//以p->father的根节点的树遍历完成,继续向上寻找p->father的父亲
while(p->father && p->father->right == p){
p = p->father;
}
//当p是其父亲的左孩子,证明p->father的左树已经遍历完,此时遍历p->father
if(p->father && p->father->left == p) return p->father;
return NULL;
}
};