当前位置:   article > 正文

Leetcode题解-数据结构-树_树题解

树题解

1、递归

1.1 树的高度

Leetcode : 104. Maximum Depth of Binary Tree (Easy)

Given a binary tree, find its maximum depth.The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node.

Note: A leaf is a node with no children.

Example:
Given binary tree [3,9,20,null,null,15,7],

      3
     / \
    9  20
       / \
      15  7
  • 1
  • 2
  • 3
  • 4
  • 5

return its depth = 3.

问题分析
树是一种递归的定义:一棵树要么是空树,要么有两个指针,每个指针指向一棵树。因此很多树相关的问题都能用递归的方式求解。

用递归思路求解求解:树如果是空树,则高度为 0,否则它的高度是两个子树高度最大值再加 1,加1是因为根节点的高度为 1。两棵子树又是树,求解子树的高度,变成递归问题。

/**
 * 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 maxDepth(TreeNode* root) {
        if(root==NULL)
            return 0;
        int x=maxDepth(root->left);
        int y=maxDepth(root->right);
        return max(x,y)+1;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

1.2 平衡树

Leetcode : 110. Balanced Binary Tree (Easy)

Given a binary tree, determine if it is height-balanced.For this problem, a height-balanced binary tree is defined as:
a binary tree in which the depth of the two subtrees of every node never differ by more than 1.

Example 1:
Given the following tree [3,9,20,null,null,15,7]:

   3
  / \
 9  20
    / \
   15  7
  • 1
  • 2
  • 3
  • 4
  • 5

Return true.

Example 2:
Given the following tree [1,2,2,3,3,null,null,4,4]:

      1
     / \
    2   2
   / \
  3   3
 / \
4   4
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

Return false.
问题分析:
给定二叉树,确定它是否是高度平衡的。高度平衡的二叉树定义为:二叉树,其中每个节点的两个子树的高度差不超过1。

/**
 * 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:
    
    bool isBalanced(TreeNode* root) {
        MaxDepth(root);
        return result;
    }
    
    int MaxDepth(TreeNode* root)
    {
        if(root==NULL)
            return 0;
        int x= MaxDepth(root->left);
        int y= MaxDepth(root->right);
        if(abs(x-y)>1)
            result=false;
        return 1+max(x,y);
    }
private:
    bool result=true;
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

1.3 归并两棵树

Leetcode : 617. Merge Two Binary Trees(Easy)
Given two binary trees and imagine that when you put one of them to cover the other, some nodes of the two trees are overlapped while the others are not.

You need to merge them into a new binary tree. The merge rule is that if two nodes overlap, then sum node values up as the new value of the merged node. Otherwise, the NOT null node will be used as the node of new tree.
Example 1:
Input:
在这里插入图片描述
Output:
在这里插入图片描述
Note: The merging process must start from the root nodes of both trees.

问题分析
归并两棵树,如果在某一个节点处,两节点都不为空,新节点值等于两节点值相加,否则只取有值的那个。

/**
 * 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:
    TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {
        if(t1==NULL&&t2==NULL)return NULL;
        if(t1==NULL)
            return t2;
        if(t2==NULL)
            return t1;
        TreeNode *tmp=(TreeNode *)malloc(sizeof(TreeNode));
        tmp->val=t1->val+t2->val;
        tmp->left=mergeTrees(t1->left, t2->left);
        tmp->right=mergeTrees(t1->right, t2->right);
        return tmp;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

1.4 判断是否存在一条路径和等于一个数

Leetcdoe : 112. Path Sum (Easy)
Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all the values along the path equals the given sum.
Note: A leaf is a node with no children.

Example:
Given the below binary tree and sum = 22, return true, as there exist a root-to-leaf path 5->4->11->2 which sum is 22.

在这里插入图片描述
题目分析
对于上面的树,题目要求的目标和为 22。该树存在一个 5 -> 4 -> 11 -> 2 的路径和为 22,因此返回 true。

递归求解思路:对于一棵树,其根节点为 root,如果根节点为空,返回false;根节点不为空,结点值为sum,且为叶子节点,返回true。再判断两个子树中是否有一棵树存在和为sum-root->val的路径。

/**
 * 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:
    bool hasPathSum(TreeNode* root, int sum) {
       if(root==NULL)
           return false;
        if((root->left==NULL&&root->right==NULL)&&root->val==sum)
            return true;
        return hasPathSum(root->left,sum-root->val)
        ||hasPathSum(root->right,sum-root->val);   
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

1.5 统计路径和等于某个数的路径总数

Leetcode : 437. Path Sum III (Medium)
You are given a binary tree in which each node contains an integer value.Find the number of paths that sum to a given value.The path does not need to start or end at the root or a leaf, but it must go downwards (traveling only from parent nodes to child nodes).
The tree has no more than 1,000 nodes and the values are in the range -1,000,000 to 1,000,000.

Example:
root = [10,5,-3,3,2,null,11,3,-2,null,1], sum = 8
在这里插入图片描述
Return 3. The paths that sum to 8 are:

  1. 5 -> 3
  2. 5 -> 2 -> 1
  3. -3 -> 11

二叉树每个节点都包含一个整数值。找到总和为给定值的路径数。路径不需要从根或叶子处开始或结束,但必须从父节点到子节点。树节点数不超过1,000个,值范围为-1000000到1000000。

问题分析
求解以根节点为起点和为sum的路径数稍微容易些,本题中起点可以为任一结点。我们可以给出以根节点为起点的,路径和为sum的路径总数的求解方案,定义这个函数为pathSumStartWithRoot。然后将所有的点作为根节点,将方案数加起来。

/**
 * 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 pathSum(TreeNode* root, int sum) {
        if(root==NULL)
            return 0;
        int result=pathSumStartWithRoot(root,sum)
        +pathSum(root->left,sum)
        +pathSum(root->right,sum);
        return result;
    }
    //以root为根节点的路径和为sum的路径个数
    int pathSumStartWithRoot(TreeNode* root,int sum)
    {
        if(root==NULL)
            return 0;
        int result=0;
        if(root->val==sum)
            result++;
        result+=pathSumStartWithRoot(root->left,sum-root->val)
        +pathSumStartWithRoot(root->right,sum-root->val);
        return result;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

1.6 子树

Leetcode 572. Subtree of Another Tree (Easy)
Given two non-empty binary trees s and t, check whether tree t has exactly the same structure and node values with a subtree of s. A subtree of s is a tree consists of a node in s and all of this node’s descendants. The tree s could also be considered as a subtree of itself.
Example 1:
Given tree s:
在这里插入图片描述
Given tree t:
在这里插入图片描述
Return true, because t has the same structure and node values with a subtree of s.

Example 2:
Given tree s:
在这里插入图片描述
Given tree t:
在这里插入图片描述
Return false.

给定两棵树 s 和 t,要求判断 t 是不是 s 的子树,t 的叶子结点也必须对应 s 的叶子节点。

问题分析
判断两棵树相等比较容易,如果对应节点的数值相同,位置相同,叶子节点对应叶子结点,则两树相同;结点数值不相同,或者结点位置不对应,两棵树不相同。
将 t 中的每个节点作为根节点,以此根节点的树判断与树 s 是否相同。问题转化为判断以 s 为根节点的树是否和 t 相同,或者判断 s 的两个子树是否存在解。用递归来实现。

/**
 * 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:
    bool isSubtree(TreeNode* s, TreeNode* t) {
        if(s==NULL)
            return false;
        return issame(s,t)||isSubtree(s->left,t)||isSubtree(s->right,t);
    }
   bool issame(TreeNode* s, TreeNode* t)
    {
        if(s==NULL&&t==NULL)
            return true;
        if(s==NULL||t==NULL)
            return false;
        if(s->val!=t->val)
            return false;
        else
            return issame(s->left,t->left)&&issame(s->right,t->right);
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

1.7 判断树是否对称

Leetcode :101. Symmetric Tree(Easy)
Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center).

For example, this binary tree [1,2,2,3,4,4,3] is symmetric:
在这里插入图片描述
But the following [1,2,2,null,3,null,3] is not:
在这里插入图片描述
Note:
Bonus points if you could solve it both recursively and iteratively.

问题分析
判断一棵树是否对称。对称是指以根节点为对称中心,左右两边的值都相等。对于子树不再要求对称。判断对称要判断的是以根节点为对称中心的两个节点是否相同,所以需要同时遍历两个节点。

/**
 * 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:
    bool isSymmetric(TreeNode* root) {
        if(root==NULL)
            return true;
        return issame(root->left,root->right);
    }
    bool issame(TreeNode* t1,TreeNode* t2)
    {
        if(t1==NULL&&t2==NULL)
            return true;
        if(t1==NULL||t2==NULL)
            return false;
        if(t1->val!=t2->val)
            return false;
        return issame(t1->left,t2->right)&&issame(t1->right,t2->left);
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

1.8 两节点间的最长路径

Leetcode : 543. Diameter of Binary Tree(Easy)
Given a binary tree, you need to compute the length of the diameter of the tree. The diameter of a binary tree is the length of the longest path between any two nodes in a tree. This path may or may not pass through the root.

Example:
Given a binary tree
在这里插入图片描述
Return 3, which is the length of the path [4,2,1,3] or [5,2,1,3].

Note: The length of path between two nodes is represented by the number of edges between them.

问题分析
给定二叉树,求树中任意两个节点之间最长路径的长度。路径可能不经过根结点。路径长度是结点之间的边数。
若路径经过根节点,则路径长度为根节点左子树的高度加上根节点右子树的高度。在求解树高度的过程种,在每个结点处,都将左子树与右子树的高度相加,不断更新最长路径长度,最终就可以得到任意两点间的最长路径长度。

/**
 * 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 pathlen=0;
    int diameterOfBinaryTree(TreeNode* root) {
        Depth(root);
        return pathlen;
    }
    int Depth(TreeNode* root)
    {
        if(root==NULL)
            return 0;
        int left=Depth(root->left);
        int right=Depth(root->right);
        pathlen=max(pathlen,left+right);
        return max(left,right)+1;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

1.9 翻转树

Leetcode : 226.Invert Binary Tree(Easy)
Invert a binary tree.
Example:

Input:
     4
   /   \
  2     7
 / \   / \
1   3 6   9

Output:
     4
   /   \
  7     2
 / \   / \
9   6 3   1
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

问题分析
问题分解,翻转之后的左子树等于根节点右子树翻转,翻转之后的右子树等于左子树翻转。

/**
 * 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:
    TreeNode* invertTree(TreeNode* root) {
        if(root==NULL)
            return NULL;
        TreeNode* left=root->left;
        root->left=invertTree(root->right);
        root->right=invertTree(left);
        return root;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

1.10 最小路径

Leetcode : 111. Minimum Depth of Binary Tree(Easy)

Given a binary tree, find its minimum depth.The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node.
Note: A leaf is a node with no children.

Example:
Given binary tree [3,9,20,null,null,15,7],
在这里插入图片描述
return its minimum depth = 2.

问题分析
求树的高度的变形,最小路径等于左子树的最小路径与右子树最小路径的较小值加1。注意:如果有一棵子树为空,只算另外一棵不为空的子树。

/**
 * 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 minDepth(TreeNode* root) {
        if(root==NULL)
            return 0;
        int left=minDepth(root->left);
        int right=minDepth(root->right);
        if(left==0||right==0)
            return left+right+1;
        return min(left,right)+1;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

1.11 统计左叶子结点的和

Leetcode : 404. Sum of Left Leaves(Easy)

Find the sum of all left leaves in a given binary tree.
Example:
在这里插入图片描述
There are two left leaves in the binary tree, with values 9 and 15 respectively. Return 24.

问题分析
树为空,返回0。根节点有左叶子,结果为该左叶子的值加右子树的所有左叶子结点。否则结果为左子树的左叶子结点和加上右子树的左叶子结点和。

/**
 * 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 sumOfLeftLeaves(TreeNode* root) {
        if(root==NULL)
            return 0;
        if(isleaves(root->left))
            return root->left->val+sumOfLeftLeaves(root->right);        
        return sumOfLeftLeaves(root->left)+sumOfLeftLeaves(root->right);;
    }
    bool isleaves(TreeNode* root)
    {
        if(root==NULL)
            return false;
        if(root->left==NULL&&root->right==NULL)
            return true;
        else
            return false;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

1.12 相同节点的最大路径长度

Leetcode : 687. Longest Univalue Path(Easy)

Given a binary tree, find the length of the longest path where each node in the path has the same value. This path may or may not pass through the root.

Note: The length of path between two nodes is represented by the number of edges between them.

Example 1:
Input:
在这里插入图片描述
Output:
2

Example 2:
Input:
在这里插入图片描述
Output:
2
Note: The given binary tree has not more than 10000 nodes. The height of the tree is not more than 1000.

问题分析
在递归函数中,首先对其左右子结点调用递归函数,得到其左右子树的最大相同值路径长度,接下来看当前结点和其左右子结点之间的关系了,如果其左子结点存在且和当前节点值相同,则L自增1,否则L为0;同理,如果其右子结点存在且和当前节点值相同,则R自增1,否则R为0。若该结点最长相同路径left+right大于path,更新path。
调用当前节点值的函数返回left和right中的较大值,原因如下:递归函数返回的是以该结点为终点的最长路径长度,这样回溯时,还可以继续连上其父结点。

举例说明:
在这里插入图片描述
若此时的node是第二层的结点4,分别对其左右子结点调用递归,会得到 L = 1, R = 0,要和父节点4组成更长的路径path,所以挑左子结点(有两个4的那边),那你会问为啥不能连上右子结点4呢,连上右子结点4是用来更新path的,不连上右子节点4为的是继续向上连接。比如若根结点也是4的话,回溯到根结点时,路径长度又增加。

/**
 * 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 path=0;
    int longestUnivaluePath(TreeNode* root) {
       longpathfromroot(root);
        return path;
    }
    int longpathfromroot(TreeNode* root)
    {
        if(root==NULL)
            return 0;
        int L=longpathfromroot(root->left);
        int R=longpathfromroot(root->right);
        int leftpath=0,rightpath=0;
        if(root->left&&root->val==root->left->val)
            leftpath=L+1;
        if(root->right&&root->val==root->right->val)
            rightpath=R+1;
        path=max(path,leftpath+rightpath);
        return max(leftpath,rightpath);
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

1.13 间隔层序遍历

Leetcode : 337.House Robber III (Medium)

The thief has found himself a new place for his thievery again. There is only one entrance to this area, called the “root.” Besides the root, each house has one and only one parent house. After a tour, the smart thief realized that “all houses in this place forms a binary tree”. It will automatically contact the police if two directly-linked houses were broken into on the same night.

Determine the maximum amount of money the thief can rob tonight without alerting the police.

Example 1:
Input: [3,2,3,null,3,null,1]
在这里插入图片描述
Output: 7
Explanation: Maximum amount of money the thief can rob = 3 + 3 + 1 = 7.

Example 2:
Input: [3,4,5,1,3,null,1]
在这里插入图片描述
Output: 9
Explanation: Maximum amount of money the thief can rob = 4 + 5 = 9.

问题分析
将二叉树结点的值加起来,使其达到最大,求值最大可以达到多大。要求父子结点不能相加,只能相加之间没有连线的结点。

将问题分解为偷根节点与不偷根节点,取二者最大值。偷根节点时,总钱数等于根节点钱数加上左右子树均不偷根节点钱数之和。
不偷根节点时,左右两颗子树可以偷根节点,也可以不偷,取两颗子树的最大值,加和。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *rooleft;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int rob(TreeNode* root) {
        if(!root) return 0;
        vector<int>res = maxrob(root);//res[0]表示偷根节点,res[1]:不偷根节点
        return max(res[0],res[1]);
    }
    vector<int> maxrob(TreeNode* root){
        vector<int>res{0,0};
        if(root==NULL) return res; 
        auto L = maxrob(root->left);
        auto R = maxrob(root->right);
        res[0] = root->val + L[1] + R[1];
        res[1] = max(L[0],L[1]) + max(R[0],R[1]);
        return res;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
/**
 * 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 rob(TreeNode* root) {
        if (root == NULL)
            return 0;
        if (root->left == NULL && root->right == NULL)
            return root->val;
        int val1 = root->val;
        if (root->left) val1 = val1 + rob(root->left->left) + rob(root->left->right);
        if (root->right) val1 = val1 + rob(root->right->left) + rob(root->right->right);
        int val2 = rob(root->left) + rob(root->right);
        return max(val1, val2);
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

1.14 二叉树中第二小的结点

Leetcode : 671. Second Minimum Node In a Binary Tree(Easy)

Given a non-empty special binary tree consisting of nodes with the non-negative value, where each node in this tree has exactly two or zero sub-node. If the node has two sub-nodes, then this node’s value is the smaller value among its two sub-nodes.

Given such a binary tree, you need to output the second minimum value in the set made of all the nodes’ value in the whole tree.If no such second minimum value exists, output -1 instead.

Example 1:
Input:
在这里插入图片描述
Output: 5
Explanation: The smallest value is 2, the second smallest value is 5.

Example 2:
Input:
在这里插入图片描述
Output: -1
Explanation: The smallest value is 2, but there isn’t any second smallest value.

问题分析
二叉树中每个非叶子结点都有两个子节点,子节点值非负。该节点的值等于两个子节点中较小的那一个,找出二叉树中第二小的那个结点,不存在这样的结点返回-1。
如果根节点有子节点,则将左右结点的值保存,如果左节点值等于根节点的值,说明一定不是第二小的结点值,以左子节点为根节点寻找第二小的结点值(递归调用)。右侧也相同。在左右子树找到的第二小结点后进行比较,若都不为-1,返回较小的那个,若其中一个为-1,返回另外一个,否则不存在,返回-1。

/**
 * 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 findSecondMinimumValue(TreeNode* root) {
        if(root==NULL)
            return -1;
        if(root->left==NULL && root->right==NULL)
              return -1;
        int leftval=root->left->val;
        int rightval=root->right->val;
        if(leftval==root->val)leftval=findSecondMinimumValue(root->left);
        if(rightval==root->val)rightval=findSecondMinimumValue(root->right);
        if(leftval!=-1&&rightval!=-1)
            return min(leftval,rightval);
        if(leftval!=-1)
             return leftval;
        return rightval;
        
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

还有一种笨办法,已知每个根节点等于两子节点的最小值,得出根节点为最小值small。直接进行前序遍历,找第二小的节点。先将 second 赋值为 0,碰见第一个不等于最小值的节点值复制给 second,将后面每个节点 val 与 second 比较,不等于 small,更新 second 为 min(val, second)

/**
 * 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 small,second = 0;
    int findSecondMinimumValue(TreeNode* root) {
        small = root->val;
        preview(root);
        if(second == 0)
            return -1;
        return second;
    }
    void preview(TreeNode* root){
        if(root == NULL) return;
        if(second == 0 && root->val != small)
            second = root->val;
        if(second != 0 && root->val != small)
            second = min(second, root->val);
        small = min(small, root->val);
        preview(root->left);
        preview(root->right);
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

2、层序遍历

2.1 二叉树的层序遍历

102. Binary Tree Level Order Traversal(Medium)

/**
 * 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:
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>>res;
        if (root == NULL) return res;
        queue<TreeNode*>q;
        q.push(root);
        while(!q.empty()){
            int q_len = q.size();
            vector<int>onelevel;
            for(int i = 0; i < q_len; i++){
                TreeNode* front = q.front();
                q.pop();
                onelevel.push_back(front->val);
                if (front->left)
                    q.push(front->left);
                if (front->right)
                    q.push(front->right);
            }
            res.push_back(onelevel);
        }
        return res;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

2.2 二叉树每层节点的平均值

637. Average of Levels in Binary Tree(Easy)
Given a non-empty binary tree, return the average value of the nodes on each level in the form of an array.

Example:

Input:
    3
   / \
  9  20
    /  \
   15   7
Output: [3, 14.5, 11]
Explanation:
The average value of nodes on level 0 is 3,  on level 1 is 14.5, and on level 2 is 11. 
Hence return [3, 14.5, 11].
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

问题分析
每求解一层的时候,队列中只包含该层的所有元素,先算出队列中有多少元素,将所有元素取出算平均值,同时将下一层元素放入队列中,取出该层所有元素时也将下一层所有元素放入队列中。

/**
 * 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:
    vector<double> averageOfLevels(TreeNode* root) {
        queue<TreeNode*>q;
        vector<double>vec;
        q.push(root);
        while(!q.empty())
        {
            int n=q.size();
            double sum=0;
            for(int i=0;i<n;i++)
            {
                sum+=q.front()->val;
                if(q.front()->left)
                    q.push(q.front()->left);
                if(q.front()->right)
                    q.push(q.front()->right);
                q.pop();
            }
            vec.push_back(sum/n);
        }
        return vec;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

2.3 找树左下角的结点

513. Find Bottom Left Tree Value(Medium)
Given a binary tree, find the leftmost value in the last row of the tree.

Example 1:

Input:
    2
   / \
  1   3
Output:
1
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

Example 2:

Input:
        1
       / \
      2   3
     /   / \
    4   5   6
       /
      7
Output:
7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

问题分析:
层序遍历,取最后一行的第一个数

/**
 * 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 findBottomLeftValue(TreeNode* root) {
        queue<TreeNode*>q;
        int res;
        q.push(root);
        while(!q.empty())
        {
            res=q.front()->val;
            int n=q.size();
            for(int i=0;i<n;i++)
            {
                if(q.front()->left)
                    q.push(q.front()->left);
                if(q.front()->right)
                    q.push(q.front()->right);
                q.pop();
            }
        }
        return res;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

2.4 之字形打印二叉树

103. Binary Tree Zigzag Level Order Traversal(Medium)
第一层从左向右打印,第二层从右向左,第三层从左向右打印……
For example:

Given binary tree [3,9,20,null,null,15,7],
    3
   / \
  9  20
    /  \
   15   7
return its zigzag level order traversal as:
[
  [3],
  [20,9],
  [15,7]
]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

方法一
用两个栈分别保存从左向右和从右向左的元素。栈中每次保存二叉树一层的数据。

/**
 * 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:
    vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
        vector<vector<int>>res;
        if(root == NULL) return res;
        stack<TreeNode*>ltor;
        stack<TreeNode*>rtol;
        ltor.push(root);
        vector<int>tmp;
        while (!ltor.empty() || !rtol.empty()){
            if (!ltor.empty()){
                while (!ltor.empty()){
                    TreeNode *t = ltor.top();
                    ltor.pop();
                    tmp.push_back(t->val);
                    if(t->left) rtol.push(t->left);
                    if(t->right) rtol.push(t->right);
                }
            }
            if(!tmp.empty()){
                res.push_back(tmp);
                tmp.clear();
            }
            if (!rtol.empty()){
                while (!rtol.empty()){
                    TreeNode *t = rtol.top();
                    rtol.pop();
                    tmp.push_back(t->val); 
                    if(t->right) ltor.push(t->right);
                    if(t->left) ltor.push(t->left);
                }
            }
            if(!tmp.empty()){
                res.push_back(tmp);
                tmp.clear();
            }
        }
        return res;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49

方法一:用map保存每层的数据,key 值为层数,key 对应的数据为每层的节点数值。统计完成后,翻转偶数层的数据。

/**
 * 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:
    map<int, vector<int>>m;
    vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
        vector<vector<int>>res;
        if(root == NULL) return res;
        BFS(root, 0);
        for(auto c : m){
            if(c.first%2)           //翻转偶数层数据(第2,4,6……层)
                reverse(c.second.begin(), c.second.end());
            res.push_back(c.second);
        }
        return res;
    }
    void BFS(TreeNode* root,int step){
        if (root == NULL) return;
        m[step].push_back(root->val);
        BFS(root->left, step + 1);
        BFS(root->right, step + 1);
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

3、前中后序遍历

3.1 非递归实现二叉树前序遍历

144. Binary Tree Preorder Traversal(Medium)
Given a binary tree, return the preorder traversal of its nodes’ values.
Example:

Input: [1,null,2,3]
   1
    \
     2
    /
   3

Output: [1,2,3]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

Follow up: Recursive solution is trivial, could you do it iteratively?

问题分析
先序、中序和后序遍历过程:遍历过程中经过结点的路线一样,只是访问各结点的时机不同。
在这里插入图片描述

从图中可以看到,前序遍历在第一次遇见元素时输出,中序遍历在第二次遇见元素时输出,后序遍历在第三次遇见元素时输出。

非递归算法实现的基本思路:使用堆栈

/**
 * 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:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int>res;
        if(root==NULL)return res;
        TreeNode* p=root;
        stack<TreeNode*>s;
        while(p!=NULL||!s.empty()){
            while(p!=NULL){
                s.push(p);
                res.push_back(p->val);
                p=p->left;
            }
            if(!s.empty()){
                p=s.top();
                s.pop();
                p=p->right;   
            }
        }
        return res;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

3.2 非递归实现二叉树中序遍历

94. Binary Tree Inorder Traversal(Medium)
Given a binary tree, return the inorder traversal of its nodes’ values.
Example:

Input: [1,null,2,3]
   1
    \
     2
    /
   3

Output: [1,3,2]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

Follow up: Recursive solution is trivial, could you do it iteratively?

问题分析:
使用栈将每个结点压入栈中,在第二次遇见元素时输出。

/**
 * 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:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int>res;
        stack<TreeNode*>s;
        TreeNode* p=root;
        while(p!=NULL||!s.empty()){
            while(p!=NULL){
                s.push(p);
                p=p->left;
            }
            if(!s.empty()){
                p=s.top();
                res.push_back(p->val);
                s.pop();
                p=p->right;
            }
        }
        return res;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

3.3 非递归实现二叉树后序遍历

145. Binary Tree Postorder Traversal(Hard)
Given a binary tree, return the postorder traversal of its nodes’ values.
Example:

Input: [1,null,2,3]
   1
    \
     2
    /
   3

Output: [3,2,1]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

Follow up: Recursive solution is trivial, could you do it iteratively?

问题分析
要保证根结点在左孩子和右孩子访问之后才能访问,因此对于任一结点P,先将其入栈。如果P不存在左孩子和右孩子,则可以直接访问它;或者P存在左孩子或者右孩子,但是其左孩子和右孩子都已被访问过了,则同样可以直接访问该结点。若非上述两种情况,则将P的右孩子和左孩子依次入栈,这样就保证了 每次取栈顶元素的时候,左孩子在右孩子前面被访问,左孩子和右孩子都在根结点前面被访问。

/**
 * 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:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int>res;
        if(root==NULL)
            return res;
        stack<TreeNode*>s;
        TreeNode* cur=NULL,*pre=NULL;
        s.push(root);
        while(!s.empty()){
            cur=s.top();
            if((cur->left==NULL&&cur->right==NULL)||
               (cur->left==pre||cur->right==pre)&&pre!=NULL){
                res.push_back(cur->val);
                pre=cur;
                s.pop();
            }
            else{
                if(cur->right)
                    s.push(cur->right);
                if(cur->left)
                    s.push(cur->left);
            }
        }
        return res;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/黑客灵魂/article/detail/788843
推荐阅读
相关标签
  

闽ICP备14008679号