• [LeetCode] 549. Binary Tree Longest Consecutive Sequence II 二叉树最长连续序列之 II


    Given a binary tree, you need to find the length of Longest Consecutive Path in Binary Tree.

    Especially, this path can be either increasing or decreasing. For example, [1,2,3,4] and [4,3,2,1] are both considered valid, but the path [1,2,4,3] is not valid. On the other hand, the path can be in the child-Parent-child order, where not necessarily be parent-child order.

    Example 1:

    Input:
            1
           / 
          2   3
    Output: 2
    Explanation: The longest consecutive path is [1, 2] or [2, 1].

    Example 2:

    Input:
            2
           / 
          1   3
    Output: 3
    Explanation: The longest consecutive path is [1, 2, 3] or [3, 2, 1].

    Note: All the values of tree nodes are in the range of [-1e7, 1e7].

    128. Longest Consecutive Sequence 的拓展,还是找最长的连续序列,这一题里可以是升序也可以是降序,而且不必从父结点到子结点,可以子父子节点。

    解法:递归。

    对于以root为根的树来说,符合条件的path可以分为两类:一类是不经过root的,一类是经过root的。不经过root的可以直接通过对其左子树和右子树的递归调用获得。经过root的有两种:一种是在其左子树上由下到上连续递增到root之后,在其右子树上由上到下连续递增;一种是在其左子树上由下到上连续递减到root之后,在其右子树上由上到下继续连续递减。我们取所有可能类型的path的最长长度即可。

    Compared with 298. Binary Tree Longest Consecutive Sequence, this question includes more different conditions since it allows for:

    1. both increasing and decreasing order from a follows the parent-child path.
    2. child-parent-child path.

    Hence this question actually contains 2 subproblems to solve:

    1. what is the longest increasing consecutive parent-child path sequence given a root node?
    2. what is the longest decreasing consecutive parent-child path sequence given a root node?

    Based on the above 2 sub-solution, we know that the longest consecutive sequence for a given root is longest_increasing_sequence + longest_decreasing_sequence from this root. We can simply add up this 2 value because the longest increasing consecutive sequence and longest decreasing consecutive sequence is guaranteed to showed up in different child path (otherwise there will be a contradiction--a child's value cannot be greater than and less than the root's value at the same time).

    If the root's value's value is not consecutive with a child's value, then the length of current sequence is simply 1.

    Time complexity: O(n) where n is the number of nodes in the tree.

    Space complexity: O(logn) on average for the recursion stack since this is a binary tree.

    Java:

    /**
     * Definition for a binary tree node.
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode(int x) { val = x; }
     * }
     */
    class Solution {
        int max = 0;
        public int longestConsecutive(TreeNode root) {
            getLongestConsecutive(root);
            return max;
        }
        
        private int[] getLongestConsecutive(TreeNode root) {
            // returns [longest_decreasing_length_from_root, longest_increasing_length_from_root]
            if (root == null) return new int[]{0, 0};
            int[] left = getLongestConsecutive(root.left);
            int[] right = getLongestConsecutive(root.right);
            int dcr = 1, icr = 1;
            if (root.left != null) {
                if (root.left.val == root.val + 1) {
                    icr = left[1] + 1;
                }
                if (root.left.val == root.val - 1) {
                    dcr = left[0] + 1;
                }
            }
            if (root.right != null) {
                if (root.right.val == root.val + 1) {
                    icr = Math.max(icr, right[1] + 1);
                } if (root.right.val == root.val - 1) {
                    dcr = Math.max(dcr, right[0] + 1);
                }
            }
            max = Math.max(max, dcr + icr - 1);
            return new int[]{dcr, icr};
        }
    }  

    Python:

    # Time:  O(n)
    # Space: O(h)
    class Solution(object):
        def longestConsecutive(self, root):
            """
            :type root: TreeNode
            :rtype: int
            """
            def longestConsecutiveHelper(root):
                if not root:
                    return 0, 0
                left_len = longestConsecutiveHelper(root.left)
                right_len = longestConsecutiveHelper(root.right)
                cur_inc_len, cur_dec_len = 1, 1
                if root.left:
                    if root.left.val == root.val + 1:
                        cur_inc_len = max(cur_inc_len, left_len[0] + 1)
                    elif root.left.val == root.val - 1:
                        cur_dec_len = max(cur_dec_len, left_len[1] + 1)
                if root.right:
                    if root.right.val == root.val + 1:
                        cur_inc_len = max(cur_inc_len, right_len[0] + 1)
                    elif root.right.val == root.val - 1:
                        cur_dec_len = max(cur_dec_len, right_len[1] + 1)
                self.max_len = max(self.max_len, cur_dec_len + cur_inc_len - 1)
                return cur_inc_len, cur_dec_len
    
            self.max_len = 0
            longestConsecutiveHelper(root)
            return self.max_len
    

    Python: 一次遍历 

    class Solution(object):
        def solve(self, root):
            inc = dec = 0
            for child in (root.left, root.right):
                if not child: continue
                cinc, cdec = self.solve(child)
                if child.val == root.val - 1:
                    dec = max(dec, cdec)
                elif child.val == root.val + 1:
                    inc = max(inc, cinc)
            self.ans = max(self.ans, inc + dec + 1)
            return inc + 1, dec + 1
        
        def longestConsecutive(self, root):
            """
            :type root: TreeNode
            :rtype: int
            """
            self.ans = 0
            if root: self.solve(root)
            return self.ans
    

    Python: 递归 + 遍历二叉树, Time: O(n^2)

    class Solution(object):
        def maxLength(self, root, val, delta):
            lchild, rchild = root.left, root.right
            lsize = rsize = 0
            if lchild and lchild.val == val + delta:
                lsize = self.maxLength(lchild, val + delta, delta)
            if rchild and rchild.val == val + delta:
                rsize = self.maxLength(rchild, val + delta, delta)
            return 1 + max(lsize, rsize)
        
        def longestConsecutive(self, root):
            """
            :type root: TreeNode
            :rtype: int
            """
            if not root: return 0
            lchild, rchild = root.left, root.right
            lsize = rsize = 0
            clen = 1
            if lchild and abs(lchild.val - root.val) == 1:
                lsize = self.maxLength(lchild, lchild.val, lchild.val - root.val)
            if rchild and abs(rchild.val - root.val) == 1:
                rsize = self.maxLength(rchild, rchild.val, rchild.val - root.val)
            if lchild and rchild and lchild.val != rchild.val:
                clen += lsize + rsize
            else:
                clen += max(lsize, rsize)
            llen = self.longestConsecutive(lchild)
            rlen = self.longestConsecutive(rchild)
            return max(clen, llen, rlen)
    

    C++:

    // Time:  O(n)
    // Space: O(h)
    
    /**
     * 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 longestConsecutive(TreeNode* root) {
            int max_len = 0;
            longestConsecutiveHelper(root, &max_len);
            return max_len;
        }
    
        pair<int, int> longestConsecutiveHelper(TreeNode *root, int *max_len) {
            if (!root) {
                return {0, 0};
            }
            const pair<int, int> left_len = longestConsecutiveHelper(root->left, max_len);
            const pair<int, int> right_len = longestConsecutiveHelper(root->right, max_len);
    
            int cur_inc_len = 1, cur_dec_len = 1;
            if (root->left) {
                if (root->left->val == root->val + 1) {
                    cur_inc_len = max(cur_inc_len, left_len.first + 1);
                } else if (root->left->val == root->val - 1){
                    cur_dec_len = max(cur_dec_len, left_len.second + 1);
                }
            }
            if (root->right) {
                if (root->right->val == root->val + 1) {
                    cur_inc_len = max(cur_inc_len, right_len.first + 1);
                } else if (root->right->val == root->val - 1) {
                    cur_dec_len = max(cur_dec_len, right_len.second + 1);
                }
            }
            *max_len = max(*max_len, cur_dec_len + cur_inc_len - 1);
            return {cur_inc_len, cur_dec_len};
        }
    };
    

    C++:

    class Solution {
    public:
        int longestConsecutive(TreeNode* root) {
            int res = 0;
            helper(root, root, res);
            return res;
        }
        pair<int, int> helper(TreeNode* node, TreeNode* parent, int& res) {
            if (!node) return {0, 0};
            auto left = helper(node->left, node, res);
            auto right = helper(node->right, node, res);
            res = max(res, left.first + right.second + 1);
            res = max(res, left.second + right.first + 1);
            int inc = 0, dec = 0;
            if (node->val == parent->val + 1) {
                inc = max(left.first, right.first) + 1;
            } else if (node->val + 1 == parent->val) {
                dec = max(left.second, right.second) + 1;
            }
            return {inc, dec};
        }
    };
    

    C++:  

    class Solution {
    public:
        int longestConsecutive(TreeNode* root) {
            if (!root) return 0;
            int res = helper(root, 1) + helper(root, -1) + 1;
            return max(res, max(longestConsecutive(root->left), longestConsecutive(root->right)));
        }
        int helper(TreeNode* node, int diff) {
            if (!node) return 0;
            int left = 0, right = 0;
            if (node->left && node->val - node->left->val == diff) {
                left = 1 + helper(node->left, diff);
            }
            if (node->right && node->val - node->right->val == diff) {
                right = 1 + helper(node->right, diff);
            }
            return max(left, right);
        }
    };
    

      

      

    类似题目:

    [LeetCode] 298. Binary Tree Longest Consecutive Sequence 二叉树最长连续序列

    [LeetCode] 128. Longest Consecutive Sequence 求最长连续序列

    [LeetCode] 300. Longest Increasing Subsequence 最长递增子序列

    [LintCode] 619 Binary Tree Longest Consecutive Sequence III 二叉树最长连续序列 III

      

    All LeetCode Questions List 题目汇总

  • 相关阅读:
    Re: 求助:5道算法题
    AutoComplete的字典建立和单词查找算法实现
    求教大牛!关于后缀树
    Qt OpenGL教程
    调试宏
    if结合errorlevel使用:判断一个DOS命令执行成功与否
    写给自己,关于对纯技术的追求,以及为了金钱与前途的技术追求
    <转>我对菜鸟成长的看法
    看完电影有感。。。。。
    <转>标准C++的类型转换符:static_cast、dynamic_cast、reinterpret_cast、和const_cast
  • 原文地址:https://www.cnblogs.com/lightwindy/p/9801750.html
Copyright © 2020-2023  润新知