1. 程式人生 > >[LeetCode] Binary Tree Longest Consecutive Sequence 二叉樹最長連續序列

[LeetCode] Binary Tree Longest Consecutive Sequence 二叉樹最長連續序列

Given a binary tree, find the length of the longest consecutive sequence path.

The path refers to any sequence of nodes from some starting node to any node in the tree along the parent-child connections. The longest consecutive path need to be from parent to child (cannot be the reverse).

For example,

   1
    \
     3
    / \
   2   4
        \
         5

Longest consecutive sequence path is 3-4-5, so return 3.

   2
    \
     3
    / 
   2    
  / 
 1

Longest consecutive sequence path is 2-3,not3-2-1, so return 2.

這道題讓我們求二叉樹的最長連續序列,關於二叉樹的題基本都需要遍歷樹,而遞迴遍歷寫起來特別簡單,下面這種解法是用到了遞迴版的先序遍歷,我們對於每個遍歷到的節點,我們看節點值是否比引數值(父節點值)大1,如果是則長度加1,否則長度重置為1,然後更新結果res,再遞迴呼叫左右子節點即可,參見程式碼如下: 

解法一:

class Solution {
public:
    int longestConsecutive(TreeNode* root) {
        if (!root) return 0;
        int res = 0;
        dfs(root, root->val, 0, res);
        return res;
    }
    void dfs(TreeNode *root, int v, int out, int &res) {
        if (!root) return;
        
if (root->val == v + 1) ++out; else out = 1; res = max(res, out); dfs(root->left, root->val, out, res); dfs(root->right, root->val, out, res); } };

下面這種寫法是利用分治法的思想,對左右子節點分別處理,如果左子節點存在且節點值比其父節點值大1,則遞迴呼叫函式,如果節點值不是剛好大1,則遞迴呼叫重置了長度的函式,對於右子節點的處理情況和左子節點相同,參見程式碼如下:

解法二:

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

下面這種遞迴寫法相當簡潔,但是核心思想和上面兩種方法並沒有太大的區別,參見程式碼如下:

解法三:

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

上面三種都是遞迴的寫法,下面我們來看看迭代的方法,寫法稍稍複雜一些,用的還是DFS的思想,以層序來遍歷樹,對於遍歷到的節點,我們看其左右子節點有沒有滿足題意的,如果左子節點比其父節點大1,若右子節點存在,則排入queue,指標移到左子節點,反之若右子節點比其父節點大1,若左子節點存在,則排入queue,指標移到右子節點,依次類推直到queue為空,參見程式碼如下:

解法四:

class Solution {
public:
    int longestConsecutive(TreeNode* root) {
        if (!root) return 0;
        int res = 0;
        queue<TreeNode*> q;
        q.push(root);
        while (!q.empty()) {
            int len = 1;
            TreeNode *t = q.front(); q.pop();
            while ((t->left && t->left->val == t->val + 1) || (t->right && t->right->val == t->val + 1)) {
                if (t->left && t->left->val == t->val + 1) {
                    if (t->right) q.push(t->right);
                    t = t->left;
                } else if (t->right && t->right->val == t->val + 1) {
                    if (t->left) q.push(t->left);
                    t = t->right;
                }
                ++len;
            }
            if (t->left) q.push(t->left);
            if (t->right) q.push(t->right);
            res = max(res, len);
        }
        return res;
    }
};

類似題目:

參考資料: