leetcode_二叉树

二叉树理论基础

二叉树的递归遍历

struct TreeNode {
	int val;
	TreeNode* left;
	TreeNode* right;
	TreeNode(int x) :val(x), left(nullptr), right(nullptr) {}
	TreeNode(int x, TreeNode* l, TreeNode* r) :val(x), left(l), right(r){}
};

//前序遍历:中左右
class Solution {
public:
	void traversal(TreeNode* cur, vector<int>& vec) {
		if (cur == nullptr) {
			return;
		}
		vec.push_back(cur->val);
		traversal(cur->left, vec);
		traversal(cur->right, vec);
	}
	vector<int> preorderTraversal(TreeNode* root) {
		vector<int> res;
		traversal(root, res);
		return res;
	}
};

//中序遍历:左中右
class Solution {
public:
	void traversal(TreeNode* cur, vector<int>& vec) {
		if (cur == nullptr) {
			return;
		}
		traversal(cur->left, vec);
		vec.push_back(cur->val);
		traversal(cur->right, vec);
	}
	vector<int> inorderTraversal(TreeNode* root) {
		vector<int> res;
		traversal(root, res);
		return res;
	}
};

//后序遍历:左右中
class Solution {
public:
	void traversal(TreeNode* cur, vector<int>& vec) {
		if (cur == nullptr) {
			return;
		}
		traversal(cur->left, vec);
		traversal(cur->right, vec);
		vec.push_back(cur->val);
	}
	vector<int> postorderTraversal(TreeNode* root) {
		vector<int> res;
		traversal(root, res);
		return res;
	}
};

二叉树的迭代遍历(统一写法:加空指针)

//节点
struct TreeNode {
	int val;
	TreeNode* left;
	TreeNode* right;
	TreeNode(int x) :val(x), left(nullptr), right(nullptr) {}
	TreeNode(int x, TreeNode* l, TreeNode* r) :val(x), left(l), right(r){}
};
//前序遍历:中左右
class Solution {
public:
	vector<int> preorderTraversal(TreeNode* root) {
		vector<int> res;
		stack<TreeNode*> st;
		if (root != nullptr)st.push(root);
		while (!st.empty()) {
			TreeNode* node = st.top();
			if (node != nullptr) {
				st.pop();
				if (node->right)st.push(node->right);
				if (node->left)st.push(node->left);
				st.push(node);
				st.push(nullptr);
			}
			else {
				st.pop();
				node = st.top();
				st.pop();
				res.push_back(node->val);
			}
		}
		return res;
	}
};

//中序遍历:左中右
class Solution {
public:
	vector<int> inorderTraversal(TreeNode* root) {
		vector<int> res;
		stack<TreeNode*> st;
		if (root != NULL)st.push(root);
		while (!st.empty()) {
			TreeNode* node = st.top();
			if (node != NULL) {
				st.pop();
				if (node->right)st.push(node->right); //stack先存右孩子节点
				st.push(node);
				st.push(nullptr);
				if (node->left)st.push(node->left);
			}
			else { //只有遇到空节点才会处理节点的下一个节点
				st.pop();
				node = st.top();
				st.pop();
				res.push_back(node->val);
			}
		}
		return res;
	}

};

//后序遍历:左右中
class Solution {
public:
	vector<int> postorderTraversal(TreeNode* root) {
		vector<int> res;
		stack<TreeNode*> st;
		if (root != nullptr)st.push(root);
		while (!st.empty()) {
			TreeNode* node = st.top();
			if (node != nullptr) {
				st.pop();
				st.push(node);
				st.push(nullptr);
				if (node->right)st.push(node->right);
				if (node->left)st.push(node->left);
			}
			else {
				st.pop();
				node = st.top();
				st.pop();
				res.push_back(node->val);
			}
		}
		return res;
	}
};

二叉树的层序遍历

迭代法

class Solution{
public:
    vector<vector<int> > levelOrder(TreeNode* root){
        queue<TreeNode*> que;
        vector<vector<int> > ans;
        if(root!=nullptr) que.push(root);
        while(!que.empty()){
            int size = que.size();
            vector<int> temp;
            for(int i =0;i<size;i++){
                TreeNode* p = que.front();
                que.pop();
                temp.push_back(p->val);
                if(p->left!=nullptr) que.push(p->left);
                if(p->right!=nullptr) que.push(p->right);
            }
            ans.push_back(temp);
        } 
        return ans;
    }
};

二叉树的层序遍历II

力扣题目链接

class Solution {
public:
    vector<vector<int>> levelOrderBottom(TreeNode* root) {
        queue<TreeNode*> que;
        vector<vector<int> > result;
        if(root!=nullptr) que.push(root);
        while(!que.empty()){
            int size = que.size();
            vector<int> res;
            for(int i =0;i<size;i++){
                TreeNode* node = que.front();
                que.pop();
                res.push_back(node->val);
                if(node->left)que.push(node->left);
                if(node->right)que.push(node->right);
            }
            result.push_back(res);
        }
        reverse(result.begin(),result.end());
        return result;
    }
};

二叉树的右视图

力扣题目链接

class Solution {
public:
    vector<int> rightSideView(TreeNode* root) {
        queue<TreeNode*> que;
        vector<int> result;
        if(root!=nullptr) que.push(root);
        while(!que.empty()){
            int size = que.size();
            vector<int> res;
            for(int i =0;i<size;i++){
                TreeNode* node = que.front();
                que.pop();
                if(i==size-1){
                    result.push_back(node->val);
                }
                if(node->left)que.push(node->left);
                if(node->right)que.push(node->right);
            }
        }
        return result;
    }
};

N叉树的层序遍历

力扣题目链接

class Solution {
public:
    vector<vector<int>> levelOrder(Node* root) {
        queue<Node*> que;
        vector<vector<int> > result;
        if(root!=nullptr) que.push(root);
        while(!que.empty()){
            int size = que.size();
            vector<int> res;
            for(int i =0;i<size;i++)
            {
                Node* node = que.front();
                que.pop();
                res.push_back(node->val);
                for(int j =0;j<node->children.size();j++)
                {
                    if(node->children[j])que.push(node->children[j]);
                }
            }
            result.push_back(res);
        }
        return result;
    }
};

填充每个节点的下一个右侧节点指针

class Solution {
public:
    Node* connect(Node* root) {
        queue<Node*> que;
        if(root!=nullptr) que.push(root);
        while(!que.empty()){
            int size = que.size();
            Node* pre;
            Node* cur;
            for(int i =0;i<size;i++)
            {
                cur = que.front();
                if(i==0){
                    pre = que.front();
                }
                else if(0<i<size-1){
                    pre->next = cur;
                    pre = cur;
                }
                else{
                    pre->next = cur;
                    pre = cur;
                    pre->next = nullptr;
                }
                que.pop();
                if(cur->left) que.push(cur->left);
                if(cur->right) que.push(cur->right);
            }
        }
        return root;
    }
};

二叉树的最大深度

前序遍历求深度,后序遍历求高度

层序遍历法(迭代)

class Solution {
public:
    int maxDepth(TreeNode* root) {
        if (root == NULL) return 0;
        int depth = 0;
        queue<TreeNode*> que;
        que.push(root);
        while(!que.empty()) {
            int size = que.size();
            depth++; // 记录深度
            for (int i = 0; i < size; i++) {
                TreeNode* node = que.front();
                que.pop();
                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
            }
        }
        return depth;
    }
};

后序遍历法(递归)

后序遍历法求的是二叉树的根节点高度,而根节点高度同样也是二叉树的最大深度。
在这里插入图片描述

class Solution {
public:
    int posttraversal(TreeNode* node,int depth){
        if(node==nullptr){
            return 0;
        }
        int leftdepth = posttraversal(node->left,depth);
        int rightdepth = posttraversal(node->right,depth);
        return 1+max(leftdepth,rightdepth);
    }
    int maxDepth(TreeNode* root) {
        int depth = 1;  //leetcode都以节点为一度
        return posttraversal(root,depth);
    }
};

二叉树的最小深度

力扣题目链接

层序遍历法

只有当左右孩子都为空的时候,才能说明遍历的最低点了,如果其中一个孩子为空则不是最低点。

class Solution {
public:
    int minDepth(TreeNode* root) {
        int depth=0;
        queue<TreeNode*> que;
        if(root!=nullptr) que.push(root);
        while(!que.empty()){
            int size = que.size();
            for(int i =0;i<size;i++){
                TreeNode* node = que.front();
                que.pop();
                if(node->left) que.push(node->left);
                if(node->right) que.push(node->right);
                if(!node->left && !node->right) return depth+1;
            }
            depth++;
        }
        return depth;
    }
};

后序遍历法

用后序遍历法的时候要注意这样一个问题:
在这里插入图片描述
如果左子树为空,右子树不为空,则最小深度是1+右子树的深度
如果右子树为空,左子树不为空,则最小深度是1+左子树的深度
如果左右子树都不为空,则最小深度是1+min(左子树深度,右子树深度)

class Solution {
public:
    int posttraversal(TreeNode* node,int depth){
        if(node==nullptr){
            return 0;
        }
        int leftdepth = posttraversal(node->left,depth);
        int rightdepth = posttraversal(node->right,depth);
        if(node->left!=nullptr && node->right==nullptr){
            return 1+leftdepth;
        }
        else if(node->right!=nullptr && node->left==nullptr){
            return 1+rightdepth;
        }
        else{
            return 1+min(leftdepth,rightdepth);
        }
    }
    int minDepth(TreeNode* root) {
        int depth=1;
        return posttraversal(root,depth);
    }
};

翻转二叉树

力扣题目链接

class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        queue<TreeNode*> que;
        if(root!=nullptr) que.push(root);
        while(!que.empty()){
            int size = que.size();
            for(int i =0;i<size;i++){
                TreeNode* node = que.front();
                que.pop();
                TreeNode* temp = node->left;
                node->left = node->right;
                node->right = temp;
                if(node->left) que.push(node->left);
                if(node->right) que.push(node->right);
            }
        }
        return root;
    }
};

完全二叉树的节点个数

力扣题目链接

完全二叉树只有两种情况:(1)满二叉树(2)最后一层叶子节点没有铺满
对于情况(1),可以直接用2^树深度-1来计算,此时根节点的深度为1
对于情况(2),分别递归其左孩子节点和右孩子节点,递归到某一深度,一定有左孩子或者有孩子为满二叉树,然后可以按照情况1计算。

迭代法

class Solution {
public:
    int countNodes(TreeNode* root) {
        if (root == nullptr) return 0;
        TreeNode* left = root->left;
        TreeNode* right = root->right;
        int leftDepth = 1, rightDepth = 1; // 这里初始为0是有目的的,为了下面求指数方便
        while (left) {  // 求左子树深度
            left = left->left;
            leftDepth++;
        }
        while (right) { // 求右子树深度
            right = right->right;
            rightDepth++;
        }
        if (leftDepth == rightDepth) {
            return pow(2,leftDepth) - 1; // 注意(2<<1) 相当于2^2,所以leftDepth初始为0
        }
        return countNodes(root->left) + countNodes(root->right) + 1;
    }
};

平衡二叉树

class Solution {
public:	
	//求某一个节点的高度,左右中后序遍历。
    int getHeight(TreeNode* node){
        if(node==nullptr){
            return 0;
        }
        int leftheight = getHeight(node->left);
        int rightheight = getHeight(node->right);
        return max(leftheight,rightheight)+1;
    }
    bool isBalanced(TreeNode* node){
        if(node==nullptr){
            return true;
        }
        //先判断左右子树分别是不是平衡二叉树,如果有一个不是,则整体一定不是,相当于运算中的剪枝。
        bool left = isBalanced(node->left);
        bool right = isBalanced(node->right);
        if(left==false||right==false){
            return false;
        }
        //如果左右子树都是,则判断根节点是否满足平衡二叉树条件。
        int leftheight = getHeight(node->left);
        int rightheight = getHeight(node->right);
        if(abs(leftheight-rightheight)<=1) return true;
        else return false;
    }
};

二叉树的所有路径

力扣题目链接

class Solution {
public:
    // 前序遍历:中左右(递归加回溯)
    void traversal(TreeNode* node,vector<int>& path,vector<string>& res)
    {
        //中:先中是因为之后的停止条件是要处理叶子节点的,而这个叶子节点是要在中的步骤里先被添加到path里
        path.push_back(node->val);
        if(node->left==nullptr && node->right==nullptr){
            string str;
            for(int i =0;i<path.size()-1;i++){
                str+= to_string(path[i]);
                str+="->";
            }
            str+=to_string(path[path.size()-1]);
            res.push_back(str);
        }
        //左
        if(node->left){
            traversal(node->left,path,res);
            path.pop_back(); //回溯
        }
        //右
        if(node->right){
            traversal(node->right,path,res);
            path.pop_back(); //回溯
        }
    }
    vector<string> binaryTreePaths(TreeNode* root) {
        vector<string> res;
        vector<int> path;
        traversal(root,path,res);
        return res;
    }
};

左叶子之和

力扣题目链接

class Solution {
public:
    int traversal(TreeNode* node, int & res){
        if(node==nullptr){
            return res;
        }
        if(node->left) traversal(node->left,res);
        if(node->right) traversal(node->right,res);
        if(node->left!=nullptr && node->left->left==nullptr && node->left->right==nullptr){
            res+=node->left->val;
            return res;
        }else{
            return res;
        }
    }
    int sumOfLeftLeaves(TreeNode* root) {
        int res=0;
        return traversal(root,res);
    }
};

找树左下角的值

力扣题目链接

使用前序遍历(中序,后序都可以),保证优先搜索左边,并且记录深度最大的叶子节点,此时就是树的最后一行最左边的值

class Solution {
public:
    int maxDepth = INT_MIN;
    int res;
    void traversal(TreeNode* node,int depth){
        if(node->left==nullptr && node->right==nullptr){
            if(depth>maxDepth){
                maxDepth = depth;
                res = node->val;
            }
        }
        //中:不处理节点
        //左:
        if(node->left){
            depth++;
            traversal(node->left,depth);
            depth--;
        }
        if(node->right){
            depth++;
            traversal(node->right,depth);
            depth--;
        }
        return ;
    }
    int findBottomLeftValue(TreeNode* root) {
        int depth = 1;
        traversal(root,depth);
        return res;
    }
};

路径总和

递归法

class Solution {
public:
    bool traversal(TreeNode* node,int count){
    	// 截止条件
        if(!node->left && !node->right){
            if(count==0) return true;
            else return false;
        }
        // 中
        // 左
        if(node->left){
            count-=node->left->val;
            if(traversal(node->left,count)) return true;
            count+=node->left->val;
        }
        //右
        if(node->right){
            count-=node->right->val;
            if(traversal(node->right,count)) return true;
            count+=node->right->val;
        }
        return false;
    }
    bool hasPathSum(TreeNode* root, int targetSum) {
        if(root) return traversal(root,targetSum-root->val);
        else return false;
        
    }
};

迭代法

class Solution {
public:
    bool hasPathSum(TreeNode* root, int targetSum) {
        if(!root) return false;
        stack<pair<TreeNode*,int> > st;
        st.push({root,root->val});
        while(!st.empty()){
            auto temp = st.top();
            st.pop();
            TreeNode* node = temp.first;
            if(!node->left && !node->right){
                if(targetSum==temp.second) return true;
            }
            if(node->right){
                st.push({node->right,temp.second+node->right->val});
            }
            if(node->left){
                st.push({node->left,temp.second+node->left->val});
            }
        }
        return false;
    }
};

从中序和后序遍历序列构造二叉树

  1. 如果数组大小(后序遍历数组,前序也可以)为零,说明是空节点了。
  2. 如果不为空,那么取后序数组最后一个元素作为节点元素
  3. 找到后序数组最后一个元素再中序数组的位置,作为切割点
  4. 切割中序数组,切成中序左数组和中序右数组(一定要先切中序数组)
  5. 切割后序数组,切成后序左数组和后序右数组
  6. 递归处理左区间和右区间

版本一

class Solution {
public:
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        //1.如果数组大小为零,说明是空节点
        if(postorder.size()==0) return nullptr;
        //2.(1)后序遍历数组最后一个元素,就是当前的中间节点
        int rootvalue = postorder[postorder.size()-1];
        TreeNode* root = new TreeNode(rootvalue);
        //2.(2)如果是叶子节点
        if(postorder.size()==1) return root;
        //3.(1)寻找切割点
        int delimiterIndex;
        for(delimiterIndex=0;delimiterIndex<inorder.size()-1;delimiterIndex++){
            if(inorder[delimiterIndex]==rootvalue) break;
        }
        //3.(2)割掉后序数组最后一个节点
        postorder.resize(postorder.size()-1);
        //4.切割中序数组,得到中序左数组和中序右数组
        //左闭右开区间
        vector<int> leftInorder(inorder.begin(),inorder.begin()+delimiterIndex);
        vector<int> rightInorder(inorder.begin()+delimiterIndex+1,inorder.end());
        //5.切割后序数组,得到后序左数组和后序右数组
        vector<int> leftpostorder(postorder.begin(),postorder.begin()+leftInorder.size());
        vector<int> rightpostorder(postorder.begin()+leftInorder.size(),postorder.end());
 		//6.递归处理左右区间
        root->left = buildTree(leftInorder,leftpostorder);
        root->right = buildTree(rightInorder,rightpostorder);

        return root;
    }
};

版本二

class Solution {
private:
    // 中序区间:[inorderBegin, inorderEnd),后序区间[postorderBegin, postorderEnd)
    TreeNode* traversal (vector<int>& inorder, int inorderBegin, int inorderEnd, vector<int>& postorder, int postorderBegin, int postorderEnd) {
        if (postorderBegin == postorderEnd) return NULL;

        int rootValue = postorder[postorderEnd - 1];
        TreeNode* root = new TreeNode(rootValue);

        if (postorderEnd - postorderBegin == 1) return root;

        int delimiterIndex;
        for (delimiterIndex = inorderBegin; delimiterIndex < inorderEnd; delimiterIndex++) {
            if (inorder[delimiterIndex] == rootValue) break;
        }
        // 切割中序数组
        // 左中序区间,左闭右开[leftInorderBegin, leftInorderEnd)
        int leftInorderBegin = inorderBegin;
        int leftInorderEnd = delimiterIndex;
        // 右中序区间,左闭右开[rightInorderBegin, rightInorderEnd)
        int rightInorderBegin = delimiterIndex + 1;
        int rightInorderEnd = inorderEnd;

        // 切割后序数组
        // 左后序区间,左闭右开[leftPostorderBegin, leftPostorderEnd)
        int leftPostorderBegin =  postorderBegin;
        int leftPostorderEnd = postorderBegin + delimiterIndex - inorderBegin; // 终止位置是 需要加上 中序区间的大小size
        // 右后序区间,左闭右开[rightPostorderBegin, rightPostorderEnd)
        int rightPostorderBegin = postorderBegin + (delimiterIndex - inorderBegin);
        int rightPostorderEnd = postorderEnd - 1; // 排除最后一个元素,已经作为节点了

        root->left = traversal(inorder, leftInorderBegin, leftInorderEnd,  postorder, leftPostorderBegin, leftPostorderEnd);
        root->right = traversal(inorder, rightInorderBegin, rightInorderEnd, postorder, rightPostorderBegin, rightPostorderEnd);

        return root;
    }
public:
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        if (inorder.size() == 0 || postorder.size() == 0) return NULL;
        // 左闭右开的原则
        return traversal(inorder, 0, inorder.size(), postorder, 0, postorder.size());
    }
};

最大二叉树

力扣题目链接

class Solution {
public:
    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
        //1.如果为空返回空指针
        if(nums.size()==0){
            return nullptr;
        }
        //2.如果不为空
        int maxPosition = max_element(nums.begin(),nums.end())-nums.begin();
        TreeNode* root = new TreeNode(nums[maxPosition]);
        //3.分割数组
        vector<int> leftorder(nums.begin(),nums.begin()+maxPosition);
        vector<int> rightorder(nums.begin()+maxPosition+1,nums.end());
        
        root->left =  constructMaximumBinaryTree(leftorder);
        root->right = constructMaximumBinaryTree(rightorder);

        return root;
    }
};

合并二叉树

力扣题目链接

递归法

class Solution {
public:
    TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
        if(root1==nullptr) return root2;
        if(root2==nullptr) return root1;
        root1->val += root2->val;
        root1->left = mergeTrees(root1->left,root2->left);
        root1->right = mergeTrees(root1->right,root2->right);
        return root1;
    }
};

迭代法

class Solution {
public:
    TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {
        if(t1==nullptr) return t2;
        if(t2==nullptr) return t1;
        queue<TreeNode*> que;
        que.push(t1);
        que.push(t2);
        while(!que.empty()){
            TreeNode* node1 = que.front();
            que.pop();
            TreeNode* node2 = que.front();
            que.pop();
            node1->val+=node2->val;
            if(node1->left!=nullptr && node2->left!=nullptr){
                que.push(node1->left);
                que.push(node2->left);
            }
            if(node1->right!=nullptr && node2->right!=nullptr){
                que.push(node1->right);
                que.push(node2->right);
            }
            if(node1->left==nullptr && node2->left!=nullptr){
                node1->left = node2->left;
            }
            if(node1->right==nullptr && node2->right!=nullptr){
                node1->right = node2->right;
            }
        }
        return t1;
    }
};

二叉搜索树中的搜索

力扣题目链接

递归法

class Solution {
public:
    int value;
    TreeNode* traversal(TreeNode* node){
        if(node==nullptr){
            return nullptr;
        }
        TreeNode* n;
        if(value>node->val){
            n = traversal(node->right);
        }
        else if(value<node->val){
            n = traversal(node->left);
        }
        else{
            return node;
        }
        return n;
    }
    TreeNode* searchBST(TreeNode* root, int val) {
        value = val;
        return traversal(root);
    }
};

验证二叉搜索树

递归法

class Solution {
public:
    TreeNode* pre = nullptr;
    bool isValidBST(TreeNode* root) {
        if(root==nullptr) return true;
        bool left = isValidBST(root->left);

        if(pre!=nullptr && pre->val>root->val) return false;
        else pre = root;

        bool right = isValidBST(root->right);
        return left && right;
    }
};

迭代法

二叉树的中序遍历

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> st;
        TreeNode* cur = root;
        while (cur != NULL || !st.empty()) {
            if (cur != NULL) { // 指针来访问节点,访问到最底层
                st.push(cur); // 将访问的节点放进栈
                cur = cur->left;                // 左
            } else {
                cur = st.top(); // 从栈里弹出的数据,就是要处理的数据(放进result数组里的数据)
                st.pop();
                result.push_back(cur->val);     // 中
                cur = cur->right;               // 右
            }
        }
        return result;
    }
};
class Solution {
public:
    bool isValidBST(TreeNode* root) {
       if(root==nullptr) return true;
       stack<TreeNode*> st;
       TreeNode* pre = nullptr;
       TreeNode* cur = root;
       while(cur!=nullptr || !st.empty()){
           if(cur!=nullptr){
               st.push(cur);
               cur=cur->left;  //左
           }
           else{
               cur = st.top();
               st.pop();
               if(pre!=nullptr && pre->val>=cur->val) return false;
               else pre = cur;
               cur = cur->right;
           }
       } 
       return true;
    }
};

二叉搜索树的最小绝对差

class Solution {
public:
    int getMinimumDifference(TreeNode* root) {
        if(root==nullptr) return 0;
        stack<TreeNode*> st;
        TreeNode* pre = nullptr;
        TreeNode* cur = root;
        int ans = INT_MAX;
        while(cur!=nullptr || !st.empty()){
            if(cur!=nullptr){
                st.push(cur);
                cur=cur->left;
            }
            else{
                cur = st.top();
                st.pop();
                if(pre!=nullptr&&abs(cur->val-pre->val)<ans){
                    ans = abs(cur->val-pre->val);
                }
                pre = cur;
                cur = cur->right;   
            }
        }
        return ans;
    }
};

二叉搜索树中的众数

递归法

class Solution {
public:
    unordered_map<int,int> map;
    bool static cmp(const pair<int,int>&a,const pair<int,int>&b){
        return a.second>b.second;
    }
    void traversal(TreeNode* node){
        if(node==nullptr){
            return;
        }
        if(node->left) traversal(node->left);
        map[node->val]++;
        if(node->right) traversal(node->right);
    }
    vector<int> findMode(TreeNode* root) {
        vector<int> res;
        if(root==nullptr) return res;
        traversal(root);
        vector<pair<int,int> > vec(map.begin(),map.end());
        sort(vec.begin(),vec.end(),cmp);
        res.push_back(vec[0].first);
        for(int i =1;i<vec.size();i++)
        {
            if(vec[i].second==vec[0].second) res.push_back(vec[i].first);
            else break;
        }
        return res;
    }
};

迭代法

class Solution {
public:
    vector<int> findMode(TreeNode* root) {
        vector<int> vec;
        int num=0,count=0,count_max=0;
        stack<TreeNode*> st;
        if(root==nullptr) return vec;
        TreeNode* pre = nullptr;
        TreeNode* cur = root;
        while(cur!=nullptr || !st.empty()){
            if(cur!=nullptr){
                st.push(cur);
                cur = cur->left;
            }
            else{
                cur = st.top();
                st.pop();
                if(pre==nullptr) count=1;
                else if(pre->val==cur->val) count++;
                else count = 1;
                if(count==count_max){
                    vec.push_back(cur->val);
                }
                else if(count>count_max){
                    vec.clear();
                    vec.push_back(cur->val);
                    count_max = count;
                }
                pre = cur;
                cur = cur->right;
            }
        }
        return vec;
    }
};

二叉树的最近公共祖先

class Solution {
public:
    TreeNode* traversal(TreeNode* node,TreeNode* p, TreeNode* q){
        if(node==p || node==q || node==nullptr) return node;
        TreeNode* left = traversal(node->left,p,q);
        TreeNode* right = traversal(node->right,p,q);
        if(left!=nullptr && right!=nullptr) return node;
        else if(left!=nullptr && right==nullptr) return left;
        else if(right!=nullptr && left==nullptr) return right;
        else return nullptr;
    }
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
       return traversal(root,p,q);
    }
};

二叉搜索树的最近公共祖先

class Solution {
public:
    TreeNode* ans=nullptr;
    int a,b;
    void traversal(TreeNode* node){
        if(node==nullptr){
            return; 
        }
        if(node->val>=a && node->val<=b) {
            ans = node;
            return;
        }
        if(node->left) traversal(node->left);
        if(node->right) traversal(node->right);
    }
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(p->val<q->val){
            a = p->val;
            b = q->val;
        }else{
            a = q->val;
            b = p->val;
        }
        if(root==nullptr) return ans;
        else{
            traversal(root);
            return ans;
        }
    }
};

二叉搜索树中的插入操作

class Solution {
public:
    void traversal(TreeNode* node, int val){
        if(node==nullptr){
            return;
        }
        if(node->val>val){
            if(node->left!=nullptr) traversal(node->left,val);
            else{
                node->left = new TreeNode(val);
            }
            return;
        }
        else{
            if(node->right!=nullptr) traversal(node->right,val);
            else{ 
                node->right = new TreeNode(val);
            }
            return ; 
        }
    }
    TreeNode* insertIntoBST(TreeNode* root, int val) {
        if(root==nullptr){
            root = new TreeNode(val);
        }
        else traversal(root,val);
        return root;
    }
};

迭代法

class Solution {
public:
    TreeNode* insertIntoBST(TreeNode* root, int val) {
        if (root == NULL) {
            TreeNode* node = new TreeNode(val);
            return node;
        }
        TreeNode* cur = root;
        TreeNode* parent = root; // 这个很重要,需要记录上一个节点,否则无法赋值新节点
        while (cur != NULL) {
            parent = cur;
            if (cur->val > val) cur = cur->left;
            else cur = cur->right;
        }
        TreeNode* node = new TreeNode(val);
        if (val < parent->val) parent->left = node;// 此时是用parent节点的进行赋值
        else parent->right = node;
        return root;
    }
};

删除二叉搜索树中的节点

  1. 没找到删除的节点,遍历到空节点就直接返回
  2. 左右孩子都为空(叶子节点),直接删除节点,返回NULL为根节点。
  3. 删除节点的左孩子为空,右孩子不为空,删除节点,右孩子补位,返回右孩子为根节点
  4. 删除节点的右孩子为空,左孩子不为空,删除节点,左孩子补位,返回左孩子为根节点
  5. 左右孩子节点都不为空,则将删除节点的左子树头结点(左孩子)放到删除节点的右子树的最左面节点的左孩子上,返回删除节点左右孩子为新的根节点

情况五:
在这里插入图片描述

递归法

class Solution {
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        //情况一
        if(root==nullptr) return root;
        //情况二
        if(root->val == key){
            if(root->left==nullptr && root->right ==nullptr){
                //使用delete来删除节点,释放内存
                delete root;
                return nullptr;
            }
        
        //情况三
            else if(root->left ==nullptr){
                if(root->right!=nullptr){
                    TreeNode* node = root->right;
                    delete root;
                    return node;
                }
            }
            // 情况四
            else if(root->right ==nullptr){
                if(root->left!=nullptr){
                    TreeNode* node = root->left;
                    delete root;
                    return node;
                }
            }
            else{
                TreeNode* cur = root->right;
                while(cur->left!=nullptr){
                    cur = cur->left;
                }
                cur->left = root->left;
                TreeNode* node1 = root;
                root = root->right;
                delete node1;
                return root;
            }
        }
        if(root->left) root->left = deleteNode(root->left,key);
        if(root->right) root->right = deleteNode(root->right,key);
        return root;
    }
};

迭代法

class Solution {
private:
    TreeNode* deleteOneNode(TreeNode* target){
        if(target == nullptr) return target;
        if(target->right==nullptr) return target->left;
        TreeNode* cur = target->right;
        while(cur->left){
            cur = cur->left;
        }
        cur->left = target->left;
        return target->right;
    }
public:
    TreeNode* deleteNode(TreeNode* root, int key) {
        if(root==nullptr) return nullptr;
        TreeNode* cur=root;
        TreeNode* pre=nullptr;
        while(cur){
            if(cur->val == key) break;
            pre = cur;
            if(cur->val>key) cur = cur->left;
            if(cur->val<key) cur = cur->right;
        }
        if(pre==nullptr){
            return nullptr;
        }
        if(pre->left->val==key && pre->left){
            pre->left = deleteOneNode(cur);
        }
        if(pre->right->val==key && pre->right){
            pre->right = deleteOneNode(cur);
        }
        return root;
    }
};

修剪二叉搜索树

递归法

class Solution {
public:
    TreeNode* trimBST(TreeNode* root, int low, int high) {
        if(root==nullptr) return nullptr;
        if(root->val<low) return trimBST(root->right,low,high);
        if(root->val>high) return trimBST(root->left,low,high);
        root->left = trimBST(root->left,low,high);
        root->right = trimBST(root->right,low,high);
        return root;
    }
};

迭代法

class Solution {
public:
    TreeNode* trimBST(TreeNode* root, int L, int R) {
        if (!root) return nullptr;

        // 处理头结点,让root移动到[L, R] 范围内,注意是左闭右闭
        while (root != nullptr && (root->val < L || root->val > R)) {
            if (root->val < L) root = root->right; // 小于L往右走
            else root = root->left; // 大于R往左走
        }
        TreeNode *cur = root;
        // 此时root已经在[L, R] 范围内,处理左孩子元素小于L的情况
        while (cur != nullptr) {
            while (cur->left && cur->left->val < L) {
                cur->left = cur->left->right;
            }
            cur = cur->left;
        }
        cur = root;

        // 此时root已经在[L, R] 范围内,处理右孩子大于R的情况
        while (cur != nullptr) {
            while (cur->right && cur->right->val > R) {
                cur->right = cur->right->left;
            }
            cur = cur->right;
        }
        return root;
    }
};

将有序数组转换为二叉搜索树

递归法

class Solution {
public:
    TreeNode* traversal(TreeNode* root,int left,int right,vector<int>& nums)
    {
        if(left==right){
            root = new TreeNode(nums[left]);
        }
        else if(left<right){
            int middle = (right+left)/2;
            root = new TreeNode(nums[middle]);
            root->left = traversal(root->left,left,middle-1,nums);
            root->right = traversal(root->right,middle+1,right,nums);
        }
        return root;
    }
    TreeNode* sortedArrayToBST(vector<int>& nums) {
        TreeNode* root = new TreeNode();
        int left=0,right=nums.size()-1;
        return traversal(root,left,right,nums);
    }
};

二叉搜索树总结

代码随想录总结
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值