1. 程式人生 > 其它 >LeetCode 1457 Pseudo-Palindromic Paths in a Binary Tree

LeetCode 1457 Pseudo-Palindromic Paths in a Binary Tree

技術標籤:leetcode簡單medium標籤

簡單題,可以訓練一下優化思想。

題意:給出一個二叉樹,每個節點的值在1-9之間,若一條從根節點到葉節點的路徑(path)包含的值可以在排列變換後形成迴文串,則我們稱這條路徑是Pseudo-Palindromic Path。

求PPP的數量。

資料範圍:1≤n≤1e5

很自然的想到自根向下的dfs維護每種數值的數量,只要做到這點已經能ac了。

最裸的dfs的話,時空複雜度均為O(n),因為dfs過程中儲存了9種value的狀態。可以使用01進行優化,即使用陣列來記錄每個value的狀態stat,每次更新一個value時,就把stat[value]^=1,然後根據stat[value]的值來維護NumberOfOdd的值,若NumberOfOdd<=1,且當前節點為葉節點,則認為搜尋到一條合法路徑。

同時,為避免傳遞引數,可以使用類似八皇后的加鎖解鎖方法,在子節點遞迴結束後將當前狀態進行還原,實際上由於異或運算的特性,只要再呼叫一次對當前value的更新即可。

這樣一來,空間複雜度就降到了常數。

程式碼如下:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    struct stat{
        int v[10];
        stat() {
            for (int i = 0; i < 10; ++i)
                v[i] = 0;
        }//v[0] is used to record the number of odd numbers
        bool check(int x){
            v[x] ^= 1;
            if (v[x]) ++v[0];
            else v[0]--;
            return v[0] <= 1;
        }
    }now;
    int ans = 0;
    void dfs(TreeNode* p){
        if (now.check(p->val) && p->left == nullptr && p->right == nullptr)
            ++ans;
        if (p->left != nullptr)
            dfs(p->left);
        if (p->right != nullptr)
            dfs(p->right);
        now.check(p->val);
    }
    int pseudoPalindromicPaths (TreeNode* root) {
        stat rt;
        dfs(root);
        return ans;
    }
};

實際上我第一次寫的時候在dfs的引數中是傳遞了stat型別的,不知道為什麼改了空間更優的寫法重新提交了一次之後,結果並沒有太大的不同。

這道題可以進行很多變種,比如不限於從根節點出發,把value的取值範圍增大等變形,應該能編出許多樹上dp甚至樹鏈剖分的題目。(由於671太菜了,就摸了)