二叉树(leetcode)

本文深入探讨二叉树的多种算法实现,包括路径之和、最近公共祖先、二叉树转链表、侧面观察、层次遍历及层平均值等核心问题。通过详细解析,帮助读者理解并掌握二叉树的深度优先与广度优先遍历技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

预备知识:

二叉树 深度优先遍历

void dfs(TreeNode *root, vector<vector<int>>& result, int &path_sum, vector<int> &path, int sum){
    if(!root){
        return;
    }
    //此时访问,前序
    dfs(root->left, result, path_sum, path, sum);
    //此时访问,中序
    dfs(root->right, result, path_sum, path, sum);
    //此时访问,后序
}

1 路径之和 113

问题:返回所有路径之和==target的路径

思路:深度优先遍历,回溯思想,先在先序那里push每一个元素,判断和是否等于target,然后在后序(处理完左右节点后)把这个值去掉,

class Solution {
public:
    vector<vector<int>> pathSum(TreeNode* root, int sum) {
        vector<vector<int>> result;
        vector<int> path;
        int path_sum = 0;
        dfs(root, result, path_sum, path, sum);
        return result;
    }
private:
    void dfs(TreeNode *root, vector<vector<int>>& result, int &path_sum, vector<int> &path, int sum){
        if(!root){
            return;
        }
        path.push_back(root->val);
        path_sum += root->val;
        if(!root->left && !root->right && path_sum == sum){
            result.push_back(path);
            // return;
        }
        dfs(root->left, result, path_sum, path, sum);
        dfs(root->right, result, path_sum, path, sum);
        path.pop_back();
        path_sum -= root->val;
    }
};

2 最近的公共祖先 236

题目:找到两个节点最近的父节点

思路:和上题差不多,采用dfs搜索 搜索到这个节点就把这个路径保存下来,两个路径相比较。

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        int finish = 0;
        TreeNode *ret = 0;
        vector<TreeNode *> path_p;
        vector<TreeNode *> path_q;
        vector<TreeNode*> temp;
        int len=0;
        dfs(root, p, finish, temp, path_p);
        temp.clear();
        finish = 0;
        dfs(root, q, finish, temp, path_q);
        if(path_p.size() < path_q.size()){
            len = path_p.size();
        }else{
            len = path_q.size();
        }
        for(int i = 0; i< len; i++){
            if(path_p[i]==path_q[i]){
                ret = path_p[i];
            }
        }
        return ret;
    }
private:
    void dfs(TreeNode *&root, TreeNode *&search, int &finish, vector<TreeNode *> &path, vector<TreeNode*>& result){
        if(!root || finish){
            return;
        }
        path.push_back(root);
        if(search == root){
            finish = 1;
            result = path;
        }
        dfs(root->left, search, finish, path, result);
        dfs(root->right, search, finish, path, result);
        path.pop_back();
    }
};

3 二叉树转链表 114

题目:给定一个二叉树,将它原地转为单链表,左置NULL,右边连起来

思路1:不满足原地,直接全部遍历一下,存到vector中,再连起来

class Solution {
public:
    void flatten(TreeNode* root) {
        vector<TreeNode*> ret;
        dfs(root, ret);
        ret.push_back(0);
        for(int i =1;i<ret.size();i++){
            ret[i-1]->left = NULL;
            ret[i-1] -> right = ret[i];
        }
    }
private:
    void dfs(TreeNode * &node, vector<TreeNode*> &ret){
        if(!node){
            return;
        }
        ret.push_back(node);
        dfs(node->left, ret);
        dfs(node->right, ret);
    }
};

思路2:递归处理左子树和右子树,在中序处理,处理完左子树,处理根节点,根.left = , 根.right =   保存last用于连接右子树的开始

class Solution {
public:
    void flatten(TreeNode *root) {
        TreeNode *last = NULL;
        preorder(root, last);
    }
private:
    void preorder(TreeNode *node, TreeNode *&last){
    if (!node){
        return;
	 }
        if (!node->left && !node->right){
            last = node;
            return;
        }
        TreeNode *left = node->left;
        TreeNode *right = node->right;
        TreeNode *left_last = NULL;
        TreeNode *right_last = NULL;
        if (left){
            preorder(left, left_last);
            node->left = NULL;
            node->right = left;
            last = left_last;
        }
        if (right){
            preorder(right, right_last);
            if (left_last){
                left_last->right = right;
            }
            last = right_last;
        }
    }
};

预备知识:

二叉树广度优先遍历

用一个队列存储节点,先进入队列的 优先遍历其左右孩子。

void BFS_print(TreeNode* root){
    std::queue<TreeNode *> Q;
    Q.push(root);
    while(!Q.empty()){
        TreeNode *node = Q.front();
        Q.pop();
       	printf("[%d]\n", node->val);
       	if (node->left){
            Q.push(node->left);
       	}
        if (node->right){
            Q.push(node->right);
        }
    }
}

 4 侧面观察二叉树 199

输出  1,3,4,6

思路:

采用广度优先遍历(层次遍历),主要是建立层和节点的关系,把层和节点绑定到一起,建立view  vector 每层都存一个值

如果view.size() 比深度小1的话就push进来,不是的话就改变这个值。

class Solution {
public:
    vector<int> rightSideView(TreeNode* root) {
        queue<pair<TreeNode *, int>> q;
        if(root){
            q.push(make_pair(root, 0));
        }
        vector<int> view;
        int depth = 0;
        while(!q.empty()){
            TreeNode *temp = q.front().first;
            depth = q.front().second;
            q.pop();
            if(view.size() == depth){
                view.push_back(temp->val);
            }else{
                view[depth] = temp->val;
            }
            if(temp->left){
                q.push(make_pair(temp->left, depth+1));
            }
            if(temp->right){
                q.push(make_pair(temp->right, depth+1));
            }
        }
        return view;
    }
};

5 二叉树的层次遍历 102

题目: 每一层存到list中再存到最后结果中 , 返回list[ list, list, ...] 

思路:按正常的队列的就可以遍历,难点是 把层和节点联系在一起,上一题是通过一个深度值,这个也可以这样,最笨的方法是queue 里面 append 节点和深度绑定, 有了节点和深度的绑定值 想做什么操作都可以

还有一种方式是先计算一下queue的长度,再设置一个count值,控制每一层的执行,拿满二叉树为例, 第一次 传入len(queue) = 0, 然后把左节点 右节点放进去, 第二轮迭代len(queue) = 2, 执行两次,queue  又添加了2*2=4个元素,第三轮len(queue)=4,。。。。

class Solution:
    def levelOrder(self, root):
        """
        :type root: TreeNode
        :rtype: List[List[int]]
        """
        if not root:
            return []
        depth = 1
        queue = [(root, depth)]
        ret = []
        cur = []
        while queue:
            count = len(queue)
            cur.clear()
            while count >0:
                node,depth = queue.pop(0)
                cur.append(node.val)
                if node.left:
                    queue.append((node.left, depth+1))
                if node.right:
                    queue.append((node.right, depth+1))
                count -= 1
            ret.append(cur.copy())
        return ret

6 二叉树的层平均值 637

思路:和上面差不多  ,通过处理层框架!记住

python代码

class Solution:
    def averageOfLevels(self, root):
        """
        :type root: TreeNode
        :rtype: List[float]
        """
        queue = []
        ret = []
        queue.append(root)
        while queue:
            count = len(queue)
            num = count
            temp_sum = 0
            while count > 0:
                node = queue.pop(0)
                temp_sum += node.val;
                if node.left:
                    queue.append(node.left)
                if node.right:
                    queue.append(node.right)
                count -= 1
            ret.append(temp_sum / num)
        return ret
            

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值