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].
這道題是之前那道Binary Tree Longest Consecutive Sequence的拓展,那道題只讓從父結點到子結點這種順序來找最長連續序列,而這道題沒有這個順序限制,我們可以任意的拐彎,這樣能找到最長的遞增或者遞減的路徑。這道題利用回溯的思想比較容易,因為當一個結點沒有子結點點時,它只需要跟其父結點進行比較,這種情況最容易處理,而且一旦葉結點處理完了,我們可以一層一層的回溯,直到回到根結點,然后再遍歷的過程中不斷的更新結果res即可。由於題目中說了要么是遞增,要么是遞減,我們不能一會遞增一會遞減,所以我們遞增遞減的情況都要統計,只是最后取最長的路徑。所以我們要知道每一個結點的最長遞增和遞減路徑的長度,當然是從葉結點算起,這樣才方便往根結點回溯。當某個結點比其父結點值大1的話,說明這條路徑是遞增的,那么當我們知道其左右子結點各自的遞增路徑長度,那么當前結點的遞增路徑長度就是左右子結點遞增路徑長度中的較大值加上1,同理如果是遞減路徑,那么當前結點的遞減路徑長度就是左右子結點遞減路徑長度中的較大值加上1,通過這種方式我們可以更新每個結點的遞增遞減路徑長度。在回溯的過程中,一旦我們知道了某個結點的左右子結點的最長遞增遞減路徑長度,那么我們可以算出當前結點的最長連續序列的長度,要么是左子結點的遞增路徑跟右子結點的遞減路徑之和加1,要么事左子結點的遞減路徑跟右子結點的遞增路徑之和加1,二者中取較大值即可,參見代碼如下:
解法一:
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}; } };
上面的方法把所有內容都寫到了一個遞歸函數中,看起來有些臃腫。而下面這種方法分了兩個遞歸來寫,相對來說簡潔一些。因為每個結點的最長連續序列長度等於其最長遞增路徑長度跟最長遞減路徑之和加1,然后分別對其左右子結點調用遞歸函數,取三者最大值,相當於對二叉樹進行了先序遍歷,參見代碼如下:
解法二:
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); } };
類似題目:
Binary Tree Longest Consecutive Sequence
參考資料:
https://discuss.leetcode.com/topic/85808/c-solution
https://discuss.leetcode.com/topic/85778/dfs-c-python-solutions
https://discuss.leetcode.com/topic/85764/neat-java-solution-single-pass-o-n