二叉树遍历

文章目录

    • 删除二叉搜索树中的节点
    • 二叉搜索树中的众数
    • 根据二叉树创建字符串
    • 二叉树的坡度
    • 最大二叉树
    • 不同的二叉搜索树 II
    • 恢复二叉搜索树
    • 二叉树的锯齿形层次遍历
    • 路径总和 II
    • 二叉树中的最大路径和
    • 二叉搜索树的最近公共祖先

删除二叉搜索树中的节点

1、删除的结点无左右子节点,那么直接将其父节点指向NULL;
2、删除的结点只有1个子节点,分左右两种情况,直接将其父节点指向删除节点的子节点;
3、删除节点有2个子节点,这是最麻烦的情况了,最好是画个图理解,具体而言:



    TreeNode* deleteNode(TreeNode* root, int key) {
        if(root==NULL) return NULL;
        if(root->val==key){
            //情况一和情况二
            if(root->left==NULL) return root->right;
            if(root->right==NULL) return root->left;
            //情况三:此时需要找到最近的一个大于当前结点值的元素
            TreeNode* RminNode=FindMin(root->right);
            root->val=RminNode->val;
            root->right=deleteNode(root->right,RminNode->val);
        }
        else if(key<root->val){
            root->left=deleteNode(root->left,key);
        }
        else if(key>root->val){
            root->right=deleteNode(root->right,key);
        }
        return root;
    }

    TreeNode* FindMin(TreeNode* root){
        if(root->left) return FindMin(root->left);
        else return root;
    }
};

二叉搜索树中的众数

利用中序求出有序的序列,然后基于这个序列来找

int Max_time=0,Max_number,n=0;
    vector<int> v;
    map<int,int> m;
    vector<int> findMode(TreeNode* root) {
        InOrder(root);
        map<int,int>::iterator it;
        for(it=m.begin();it!=m.end();it++){
            if(it->second>Max_time){
                Max_time=it->second;
                Max_number=it->first;
            }
        }
        for(it=m.begin();it!=m.end();it++){
            if(it->second==Max_time){
                v.push_back(it->first);
            }
        }
        
        return v;
    }
    void InOrder(TreeNode* root){
        if(root==NULL) return ;
        InOrder(root->left);
        if(m.find(root->val)!=m.end()) m[root->val]++;//已经存在map中了
        else m.insert(pair<int,int>(root->val,1));
        InOrder(root->right);
    }

根据二叉树创建字符串

二叉树遍历_第1张图片
利用先序遍历,注意下按照递归的思想去加括号,注意只有右子树存在也要加两对括号

    string ans="";
    string tree2str(TreeNode* t) {
        PreOrder(t);
        return ans;
    }

    void PreOrder(TreeNode* root){//pos代表当前根结点的位置
        if(root==NULL) return;
        ostringstream os;
        os<<root->val;
        ans+=os.str();
        if(root->right){//右子树存在,则左右都要有括号
            ans+='(';
            PreOrder(root->left);
            ans+=')';
            ans+='(';
            PreOrder(root->right);
            ans+=')';
        }
        else if(root->left){//只有左子树存在,右子树的括号不用写
            ans+='(';
            PreOrder(root->left);
            ans+=')';
        }
    }

二叉树的坡度

二叉树遍历_第2张图片
就是一个计算和的递归就行,很简单

    int ans=0;
    int findTilt(TreeNode* root) {
        SumTree(root);
        return ans;

    }

    int SumTree(TreeNode* root){
        if(root==NULL) return 0;
        int lsum=SumTree(root->left);
        int rsum=SumTree(root->right);
        ans+=abs(lsum-rsum);
        return root->val+lsum+rsum;

    }

最大二叉树

二叉树遍历_第3张图片
用双指针(left,right)+递归实现,注意传参的类型!!

    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
        return solve(nums.begin(),nums.end());
    }

    TreeNode* solve(vector<int>::iterator left, vector<int>::iterator right){
        if(left == right) return NULL;
        auto it = max_element(left,right);
        TreeNode* node = new TreeNode(*it);
        node->left = solve(left,it);
        node->right = solve(it+1,right);
        return node;
    }

不同的二叉搜索树 II

二叉树遍历_第4张图片
这里递归就是先拆分,得到最底层的值后再合并,
拆分就是分成左右子树,最终就是start>end 返回{NULL}。
合并的时候要用两个for循环来实现不同的排列。。。
注:若只是求种数,可以用卡塔兰数计算
二叉树遍历_第5张图片

vector<TreeNode*> generateTrees(int n) {
        vector<TreeNode*> res;
        if(n==0) return res;
        return generateTreesCore(1, n);
        
    }
    vector<TreeNode*> generateTreesCore(int start, int end){
        vector<TreeNode*> res;
        if(start>end){
            return {NULL};
        }
        else{
            for(int i = start;i<=end;++i){//表示以i为节点构建树
                vector<TreeNode*> left = generateTreesCore(start, i-1);//构建左子树
                vector<TreeNode*> right = generateTreesCore(i+1, end);//构建右子树

                //此时左右子树都有值.要把他们合并在一起。
                for(auto r: right){
                    for(auto l: left){
                        TreeNode* temp = new TreeNode(i);//把每个节点构建出来。
                        temp->left = l;
                        temp->right = r;
                        res.push_back(temp);
                    }
                }
            }
        }
        return res;
    }

恢复二叉搜索树

二叉树遍历_第6张图片

 	vector<int> order;
    void recoverTree(TreeNode* root) {
        InOrder(root);
        //先得到正确的序列
        sort(order.begin(),order.end());
        recover(root,order);
    }

    void InOrder(TreeNode* root){
        if(root==NULL) return ;
        InOrder(root->left);
        order.push_back(root->val);
        InOrder(root->right);
    }

    void recover(TreeNode* root,vector<int>& rec){
        if(root ==NULL){
            return;
        }
        recover(root->left,rec);
        //
        if(root->val == rec[0]){
            rec.erase(rec.begin());
        }else{
            //若不同则修改为相同
            root->val = rec[0];
            rec.erase(rec.begin());
        };

        recover(root->right,rec);
    }

二叉树的锯齿形层次遍历

//q1记录正序,q2记录反序
    queue<TreeNode*> q1;
    queue<TreeNode*> q2;
    vector<vector<int>> ans;
    vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
        if(root==NULL) return ans;
        q1.push(root);
        q2.push(root);
        TreeNode* pre_last1=root;
        TreeNode* last1=root;
        TreeNode* pre_last2=root;
        TreeNode* last2=root;
        int level=0;
        vector<int> temp;
        while(!q1.empty()&&!q2.empty()){
            TreeNode* p1=q1.front();
            q1.pop();
            TreeNode* p2=q2.front();
            q2.pop();
            if(p1->left){
                last1=p1->left;
                q1.push(p1->left);
            }
            if(p1->right){
                last1=p1->right;
                q1.push(p1->right);
            }
            if(p2->right){
                last2=p2->right;
                q2.push(p2->right);
            }
            if(p2->left){
                last2=p2->left;
                q2.push(p2->left);
            }
            if(level==0) temp.push_back(p1->val);
            else temp.push_back(p2->val);
            //两个同时到达当前行的最后一个
            if(p1==pre_last1){
                pre_last1=last1;
                pre_last2=last2;
                if(level==0){
                    ans.push_back(temp);
                    temp.clear();
                    level=1;
                }
                else{
                    ans.push_back(temp);
                    temp.clear();
                    level=1-level;
                }
            }
        }
        return ans;
    }

路径总和 II

二叉树遍历_第7张图片

	int target;
    bool flag=false;
    vector<vector<int>> ans;
    vector<vector<int>> pathSum(TreeNode* root, int sum) {
        if(root==NULL) return ans;
        target=sum;
        vector<int> temp;
        temp.push_back(root->val);
        dfs(root,0,temp);
        return ans;
    }

    void dfs(TreeNode* root,int sum,vector<int>& temp){
        int cur_sum=sum+root->val;
        //cout<
        if(root->left==NULL&&root->right==NULL){
            if(sum+root->val==target){
                ans.push_back(temp);
                flag=true;
                return ;
            }
        }
            if(root->left){
                temp.push_back(root->left->val);
                dfs(root->left,cur_sum,temp);
                temp.pop_back();
            }
            if(root->right){
                temp.push_back(root->right->val);
                dfs(root->right,cur_sum,temp);
                temp.pop_back();
            }
    }

二叉树中的最大路径和

二叉树遍历_第8张图片

public:
    int maxh;
    int maxPathSum(TreeNode* root) {
        //if(root==NULL) return 0;
        maxh=root->val;
        max_path(root);
        return maxh;
    }

    int max_path(TreeNode* root){
        if(root==NULL) return 0;
        int cur=root->val;
        int l=max_path(root->left)+cur;
        int r=max_path(root->right)+cur;
        //cout<<"root"<val<
        //cout<<"left:"<
        if(l>maxh) maxh=l;
        if(r>maxh) maxh=r;
        if(l+r-cur>maxh) maxh=l+r-cur;
        //加上这个是因为有的防止每次计算最大路径都必须包括叶结点(对于已经小于0的分支可以直接抛弃)
        if(l<0&&r<0) return 0;
        else return max(l,r);
    }

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

二叉树遍历_第9张图片

/*
两个节点p,q分为两种情况:

p和q在相同子树中
p和q在不同子树中
从根节点遍历,递归向左右子树查询节点信息
递归终止条件:如果当前节点为空或等于p或q,则返回当前节点

递归遍历左右子树,如果左右子树查到节点都不为空,则表明p和q分别在左右子树中,因此,当前节点即为最近公共祖先;
如果左右子树其中一个不为空,则返回非空节点。
*/
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(root==NULL||root==p||root==q) return root; 
        TreeNode* left=lowestCommonAncestor(root->left,p,q);
        TreeNode* right=lowestCommonAncestor(root->right,p,q);
        if(left&&right) return root;
        if(left==NULL) return right;
        else return left;
    }

你可能感兴趣的:(算法)