LeetCode 1457 Pseudo-Palindromic Paths in a Binary Tree
阿新 • • 發佈:2021-01-11
簡單題,可以訓練一下優化思想。
題意:給出一個二叉樹,每個節點的值在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太菜了,就摸了)