递归算法——Leetcode题型总结(1)

二叉树专题

1,最长同值路径(Leetcode 687 题)

题目描述:给定一个二叉树,找到最长的路径,这个路径中的每个节点具有相同值。 这条路径可以经过也可以不经过根节点。

注意:两个节点之间的路径长度由它们之间的边数表示。

示例 1:

输入:

          5
         / \
        4   5
       / \   \
      1   1   5

输出:2

示例 2:

输入:

          1
         / \
        4   5
       / \   \
      4   4   5

输出:2

本题题目链接:
https://leetcode-cn.com/problems/longest-univalue-path/.

题目解析:
在解决此题前,先看一道类似的基础题,即力扣第543题

1.1 二叉树的直径(543题)

题目链接如下:
https://leetcode-cn.com/problems/diameter-of-binary-tree/.

该题题目描述为:

给定一棵二叉树,你需要计算它的直径长度。一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过也可能不穿过根结点。

示例 :
给定二叉树

      1
     / \
    2   3
   / \     
  4   5    

返回 3, 它的长度是路径 [4,2,1,3] 或者 [5,2,1,3]。
注意:两结点之间的路径长度是以它们之间边的数目表示

题解:(参考官方题解)
首先我们知道一条路径的长度为该路径经过的节点数减一,所以求直径(即求路径长度的最大值)等效于求路径经过节点数的最大值减一。

而任意一条路径均可以被看作由某个节点为起点,从其左儿子和右儿子向下遍历的路径拼接得到。
力扣官方图
如图我们可以知道路径 [9, 4, 2, 5, 7, 8] 可以被看作以 22 为起点,从其左儿子向下遍历的路径 [2, 4, 9] 和从其右儿子向下遍历的路径 [2, 5, 7, 8] 拼接得到。

假设我们知道对于该节点的左儿子向下遍历经过最多的节点数 L(即以左儿子为根的子树的深度) 和其右儿子向下遍历经过最多的节点数 R (即以右儿子为根的子树的深度),那么以该节点为起点的路径经过节点数的最大值即为 L+R+1 。

我们记节点 node 为起点的路径经过节点数的最大值为 d,那么二叉树的直径就是所有节点 d 的最大值减一。

代码为:(543)

class Solution {
public:
    int ans; //最大直径长度路径的结点数
    int diameterOfBinaryTree(TreeNode* root) {
        ans=1;
        dfs(root);
        return ans-1;//最大直径长度
    }
    int dfs(TreeNode* node)
    {
        if(node==NULL) return 0;//如果结点不存在,返回0(针对叶子结点),此为递归返回条件
        int L=dfs(node->left); //当前结点左子树深度
        int R=dfs(node->right); //当前结点右子树深度
        ans=max(ans,L+R+1); //L+R+1为经过当前节点的最长路径包含的结点数,与ans相比取最大值
        return max(L,R)+1;//当前结点深度
    }
};

做完这道题之后,回过头看第687题,发现这两道题是类似的,不过第687题要求结点值相同的最大路径长度。
采用自底向上的方法来解决这道题,从一个结点 nod e出发,向它的左右子树分别发射两个箭头,箭头经过的结点的值均和 node 的值相等,箭头的长度为左/右子树中最长的同值路径长度+1(加1是因为要加上从node到左/右子树根节点的路径长度),而最长同值路径长度 ans=max( ((左子树最长同值路径长度+1 )+(右子树最长同值路径长度+1 )),ans),这个公式可能太绕了,不过意思就是求出经过该结点 node 的最长同值路径长度。最后比较得到整棵树的最大的 ans。

代码如下:(687)

class Solution {
public:
    int ans;// 最大同值路径长度
    int longestUnivaluePath(TreeNode* root) {
        ans=0;
        maxarrowlength(root);
        return ans;
    }
    int maxarrowlength(TreeNode* node)
    {
        if(node==NULL) return 0;//终止条件
        int L=maxarrowlength(node->left);//当前结点左子树最大同值路径长度
        int R=maxarrowlength(node->right);//当前结点右子树最大同值路径长度
        int arrowL=0,arrowR=0;//
        if(node->left!=NULL&&node->left->val==node->val)
        {
            arrowL=L+1;
        }                        //若当前结点与左子树根结点值相同,则从结点向左子树射出的箭头长度为L+1
        if(node->right!=NULL&&node->right->val==node->val)
        {
            arrowR=R+1;
        }                      //同上
        ans=max(ans,arrowL+arrowR);//最大同值路径为当前结点左右箭头长度相加与ans相比的较大值
        return max(arrowL,arrowR);//返回当前结点左右子树中较大的那个同值路径
    }
};

几道相关题目:
104题链接: https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/.
1367题链接: https://leetcode-cn.com/problems/linked-list-in-binary-tree/.
1372题链接: https://leetcode-cn.com/problems/longest-zigzag-path-in-a-binary-tree/.
124题链接: https://leetcode-cn.com/problems/binary-tree-maximum-path-sum/.

2,BiNode

3,二叉搜索树的范围和(938)

4,二叉搜索树节点最小距离(783)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值