二叉树------遍历二叉树(含题目)

  二叉树是每个节点最多有两个子树的树结构。它有五种基本形态:二叉树可以是空集;根可以有空的左子树或右子树;活着左、右子树皆为空。二叉树的结构很美妙,只有以下五种情况:

(图是@Begin to change的创作的!)

要理解递归算法,最好是从二叉树入手,很多一般递归的题目都可以从二叉树的递归中找到影子!!,可以说理解好二叉树是理解递归的前提(自己深有体会!!!!!)

首先从三种遍历方式开头:前序遍历,中序遍历,后序遍历。 

前序遍历的顺序是先访问根节点,然后递归地先序遍历左子树,再递归地先序遍历右子树。

Python: 

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        ans = []
        def preorder(root):
            if root is None:
                return
            ans.append(root.val)
            preorder(root.left)
            preorder(root.right)
        preorder(root)
        return ans
        

C++:

/**
 * 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 Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> ans;
        function<void(TreeNode*)> preorder = [&](TreeNode* root) {
            if (root == nullptr) {
                return;
            }
            ans.push_back(root->val);
            preorder(root->left);
            preorder(root->right);
        };
        preorder(root);
        return ans;
    }
};

中序遍历首先访问左子树,然后访问根节点,最后访问右子树。中序遍历对于二叉搜索树尤其有用,因为它可以按升序访问所有节点。

Python:

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        ans = []
        def inorder(root):
            if root is None:
                return
            inorder(root.left)
            ans.append(root.val)
            inorder(root.right)
        inorder(root)
        return ans

C++:

/**
 * 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 Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> ans;
        function<void(TreeNode*)> inorder = [&](TreeNode* root) {
            if (root == nullptr) {
                return;
            }
            inorder(root->left);
            ans.push_back(root->val);
            inorder(root->right);
        };
        inorder(root);
        return ans;
    }
};

后序遍历:1.访问左子树;2.访问右子树;3.完成该节点的左右子树的访问后,再访问该节点。即考察到一个节点后,将其暂存,遍历完左右子树后,再输出该节点的值。

Python:

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        ans = []
        def postorder(root):
            if root is None:
                return 
            postorder(root.left)
            postorder(root.right)
            ans.append(root.val)
        postorder(root)
        return ans

C++:

/**
 * 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 Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> ans;
        function<void(TreeNode*)> postorder = [&](TreeNode* root) {
            if (root == nullptr) {
                return;
            }
            postorder(root->left);
            postorder(root->right);
            ans.push_back(root->val);
        };
        postorder(root);
        return ans;
    }
};

在看接下来的题目之前,我先讲一下我对于递归算法的理解,希望能对大家有帮助。

我认为,在看到一颗二叉树的时候,可能这颗二叉树有很多分支,很多节点,反正就是很复杂,很复杂的数。这个时候就把这一颗树抽象成一个根节点和它的左右儿子,也就是把n个节点的树抽象成只有三个节点的树,然后在这上面思考,这个时候就会变得简单很多。

接下来是几个题目:

872. 叶子相似的树

题目要求从左到右顺序排列子节点的值,也就是说要先遍历左子树,再遍历右子树,并且要判断这个点是否是叶子节点 。我的主要思路是:分别将两个树的叶子节点用列表的形式拿出来,然后进行比较,看是否相等。(就按照上面的方法很好理解),我的代码:

Python:

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def leafSimilar(self, root1: Optional[TreeNode], root2: Optional[TreeNode]) -> bool:
        arr1, arr2 = [], []
        # 这里其实可以写一个函数进行复用,减少代码量
        def find1(node):
            if not node.left and not node.right:
                arr1.append(node.val)
            if node.left:
                find1(node.left)
            if node.right:
                find1(node.right)
        def find2(node):
            if not node.left and not node.right:
                arr2.append(node.val)
            if node.left:
                find2(node.left)
            if node.right:
                find2(node.right)
        find1(root1)
        find2(root2)
        return arr1 == arr2

C++

/**
 * 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 Solution {
public:
    bool leafSimilar(TreeNode* root1, TreeNode* root2) {
        vector<int> ans1, ans2;
        function<void(TreeNode*, vector<int>&)> find = [&](TreeNode* root, vector<int>& arr) {
            if (root->left == root->right) {
                arr.push_back(root->val);
            }
            if (root->left) {
                find(root->left, arr);
            }
            if (root->right) {
                find(root->right, arr);
            }
        };
        find(root1, ans1);
        find(root2, ans2);
        if (ans1 == ans2) {
            return true;
        }
        return false;
    }
};

这个题目就是将所有节点的颜色记录下来然后去重就可以了,要实现上述操作,可以使用C++里面和Python的set容器。

Python:

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:
    def numColor(self, root: TreeNode) -> int:
        cnt = set()
        def dfs(root):
            if (root is None):
                return
            cnt.add(root.val)
            dfs(root.left)
            dfs(root.right)
        dfs(root)
        return len(cnt)

C++:

/**
 * 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 numColor(TreeNode* root) {
        set<int> cnt;
        function<void(TreeNode*)> dfs = [&](TreeNode* root) {
            if (root == nullptr) {
                return;
            }
            cnt.insert(root->val);
            dfs(root->left);
            dfs(root->right);
        };
        dfs(root);
        return cnt.size();
    }
};

这个题一开始我有点不太会写,因为按照先遍历左子树,再遍历右子树的逻辑,那么就会同时加上左子树的叶子节点和右子树叶子节点的值,显然是不符合题意的。结果我发现我的点笨!!!只需要在判断左子树的时候改变ans的值就可以做到只保留左叶子节点的值了,如果右子树不为空的话,正常往下遍历就行了。

Python:

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def sumOfLeftLeaves(self, root: Optional[TreeNode]) -> int:
        ans = 0
        def dfs(root):
            nonlocal ans
            if root is None:
                return
            if root.left:
                if root.left.left == root.left.right:
                    ans += root.left.val
                else:
                    dfs(root.left)
            if root.right:
                dfs(root.right)
        dfs(root)
        return ans

C++:

/**
 * 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 Solution {
public:
    int sumOfLeftLeaves(TreeNode* root) {
        int ans = 0;
        function<void(TreeNode*)> dfs = [&](TreeNode* root) {
            if (root == nullptr) {
                return;
            }
            if (root->left) {
                if (root->left->left == root->left->right) {
                    ans += root->left->val;
                }
                else {
                    dfs(root->left);
                }
            }
            if (root->right) {
                dfs(root->right);
            }
        };
        dfs(root);
        return ans;
    }
};

第一种方法:

        这种方法比较好理解,就是用一个容器,将所有的节点的值通过遍历一遍二叉树后存储下来,然后进行排序去重操作,就能得到答案了。

Python:

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def findSecondMinimumValue(self, root: Optional[TreeNode]) -> int:
        cnt = set()
        def dfs(root):
            if root is None:
                return
            cnt.add(root.val)
            dfs(root.left)
            dfs(root.right)
        dfs(root)
        if len(cnt) < 2:
            return -1
        # sort() 方法是对列表进行原地排序,它不会返回排序后的列表,而是返回 None
        # sorted_list = list(cnt).sort()
        sorted_list = list(cnt)
        sorted_list.sort()
        return sorted_list[1]

C++:

/**
 * 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 Solution {
public:
    int findSecondMinimumValue(TreeNode* root) {
        vector<int> cnt;
        function<void(TreeNode*)> dfs = [&](TreeNode* root) {
            if (root == nullptr) {
                return;
            }
            cnt.push_back(root->val);
            dfs(root->left);
            dfs(root->right);
        };
        dfs(root);
        sort(cnt.begin(), cnt.end());
        cnt.erase(unique(cnt.begin(), cnt.end()), cnt.end());
        if (cnt.size() < 2) {
            return -1;
        }
        return cnt[1];
    }
};

第二种方法:

        定义一个变量来存储,但是说实话我感觉好像差不多~~~。

Python:

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def findSecondMinimumValue(self, root: Optional[TreeNode]) -> int:
        ans, route = -1, root.val #根节点是最小的
        def dfs(root):
            nonlocal ans
            if root is None:
                return
            if ans != -1 and root.val >= ans:
                return
            if root.val > route:
                ans = root.val
            dfs(root.left)
            dfs(root.right)
        dfs(root)
        return ans

C++:

/**
 * 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 Solution {
public:
    int findSecondMinimumValue(TreeNode* root) {
        int ans = -1;
        int route = root->val;
        function<void(TreeNode*)> dfs = [&](TreeNode* node) {
            if (node == nullptr) {
                return;
            }
            if (ans != -1 && node->val >= ans) {
                return;
            }
            if (node->val > route) {
                ans = node->val;
            }
            dfs(node->left);
            dfs(node->right);
        };
        dfs(root);
        return ans;
    }
};

到这里就完结啦~~~~如果能把以上的题目都弄懂,那么对于二叉树有一定了解了,对于后面的学习会更加顺利,加油!!!!。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值