5454
5555<!-- 这里可写通用的实现逻辑 -->
5656
57- 先序遍历,统计每条路径上数字出现的次数,要满足伪回文路径,当且仅当路径上最多有一个数字的出现次数为奇数。
57+ ** 方法一:DFS + 位运算**
58+
59+ 一条路径是伪回文路径,当且仅当该路径经过的节点值的出现次数为奇数的数字为 $0$ 个或 $1$ 个。
60+
61+ 由于二叉树节点值的范围为 $1$ 到 $9$,因此对于每一条从根到叶子的路径,我们可以用一个长度为 $10$ 的二进制数 $mask$ 表示当前路径经过的节点值的出现状态,其中 $mask$ 的第 $i$ 位为 $1$,表示当前路径上节点值 $i$ 的出现次数为奇数,否则表示其出现次数为偶数。那么,如果一条路径是伪回文路径,需要满足 $mask \& (mask - 1) = 0$,其中 $\& $ 表示按位与运算。
62+
63+ 基于以上分析,我们可以使用深度优先搜索的方法计算路径数。我们定义一个函数 $dfs(root, mask)$,表示从当前 $root$ 节点开始,且当前节点的状态为 $mask$ 的所有伪回文路径的个数。那么答案就是 $dfs(root, 0)$。
64+
65+ 函数 $dfs(root, mask)$ 的执行逻辑如下:
66+
67+ 如果 $root$ 为空,则返回 $0$;
68+
69+ 否则,令 $mask = mask \oplus 2^{root.val}$,其中 $\oplus$ 表示按位异或运算。
70+
71+ 如果 $root$ 是叶子节点,那么如果 $mask \& (mask - 1) = 0$,返回 $1$,否则返回 $0$;
72+
73+ 如果 $root$ 不是叶子节点,返回 $dfs(root.left, mask) + dfs(root.right, mask)$。
74+
75+ 时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是二叉树的节点数。
5876
5977<!-- tabs:start -->
6078
7088# self.left = left
7189# self.right = right
7290class Solution :
73- def pseudoPalindromicPaths (self , root : TreeNode) -> int :
74- def dfs (root ):
91+ def pseudoPalindromicPaths (self , root : Optional[ TreeNode] ) -> int :
92+ def dfs (root : Optional[TreeNode], mask : int ):
7593 if root is None :
76- return
77- nonlocal ans, counter
78- counter[root.val] += 1
94+ return 0
95+ mask ^= 1 << root.val
7996 if root.left is None and root.right is None :
80- if sum (1 for i in range (1 , 10 ) if counter[i] % 2 == 1 ) < 2 :
81- ans += 1
82- else :
83- dfs(root.left)
84- dfs(root.right)
85- counter[root.val] -= 1
86-
87- ans = 0
88- counter = [0 ] * 10
89- dfs(root)
90- return ans
97+ return int ((mask & (mask - 1 )) == 0 )
98+ return dfs(root.left, mask) + dfs(root.right, mask)
99+
100+ return dfs(root, 0 )
91101```
92102
93103### ** Java**
@@ -111,40 +121,19 @@ class Solution:
111121 * }
112122 */
113123class Solution {
114- private int ans;
115- private int [] counter;
116-
117124 public int pseudoPalindromicPaths (TreeNode root ) {
118- ans = 0 ;
119- counter = new int [10 ];
120- dfs(root);
121- return ans;
125+ return dfs(root, 0 );
122126 }
123127
124- private void dfs (TreeNode root ) {
128+ private int dfs (TreeNode root , int mask ) {
125129 if (root == null ) {
126- return ;
130+ return 0 ;
127131 }
128- ++ counter[ root. val] ;
132+ mask ^ = 1 << root. val;
129133 if (root. left == null && root. right == null ) {
130- if (check(counter)) {
131- ++ ans;
132- }
133- } else {
134- dfs(root. left);
135- dfs(root. right);
136- }
137- -- counter[root. val];
138- }
139-
140- private boolean check (int [] counter ) {
141- int n = 0 ;
142- for (int i = 1 ; i < 10 ; ++ i) {
143- if (counter[i] % 2 == 1 ) {
144- ++ n;
145- }
134+ return (mask & (mask - 1 )) == 0 ? 1 : 0 ;
146135 }
147- return n < 2 ;
136+ return dfs(root . left, mask) + dfs(root . right, mask) ;
148137 }
149138}
150139```
@@ -165,30 +154,18 @@ class Solution {
165154 */
166155class Solution {
167156public:
168- int ans;
169- vector<int > counter;
170-
171157 int pseudoPalindromicPaths(TreeNode* root) {
172- ans = 0;
173- counter.resize(10);
174- dfs(root);
175- return ans;
176- }
177-
178- void dfs (TreeNode* root) {
179- if (!root) return;
180- ++counter[ root->val] ;
181- if (!root->left && !root->right) {
182- int n = 0;
183- for (int i = 1; i < 10; ++i)
184- if (counter[ i] % 2 == 1)
185- ++n;
186- if (n < 2) ++ans;
187- } else {
188- dfs(root->left);
189- dfs(root->right);
190- }
191- --counter[ root->val] ;
158+ function<int(TreeNode* , int)> dfs = [ &] (TreeNode* root, int mask) {
159+ if (!root) {
160+ return 0;
161+ }
162+ mask ^= 1 << root->val;
163+ if (!root->left && !root->right) {
164+ return (mask & (mask - 1)) == 0 ? 1 : 0;
165+ }
166+ return dfs(root->left, mask) + dfs(root->right, mask);
167+ };
168+ return dfs(root, 0);
192169 }
193170};
194171```
@@ -205,32 +182,101 @@ public:
205182 * }
206183 */
207184func pseudoPalindromicPaths(root *TreeNode) int {
208- ans := 0
209- counter := make([]int, 10)
210- var dfs func(root *TreeNode)
211- dfs = func(root *TreeNode) {
185+ var dfs func(*TreeNode, int) int
186+ dfs = func(root *TreeNode, mask int) int {
212187 if root == nil {
213- return
188+ return 0
214189 }
215- counter[ root.Val]++
190+ mask ^= 1 << root.Val
216191 if root.Left == nil && root.Right == nil {
217- n := 0
218- for i := 1; i < 10; i++ {
219- if counter[i]%2 == 1 {
220- n++
221- }
222- }
223- if n < 2 {
224- ans++
192+ if mask&(mask-1) == 0 {
193+ return 1
225194 }
226- } else {
227- dfs(root.Left)
228- dfs(root.Right)
195+ return 0
229196 }
230- counter[ root.Val]--
197+ return dfs( root.Left, mask) + dfs(root.Right, mask)
231198 }
232- dfs(root)
233- return ans
199+ return dfs(root, 0)
200+ }
201+ ```
202+
203+ ### ** TypeScript**
204+
205+ ``` ts
206+ /**
207+ * Definition for a binary tree node.
208+ * class TreeNode {
209+ * val: number
210+ * left: TreeNode | null
211+ * right: TreeNode | null
212+ * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
213+ * this.val = (val===undefined ? 0 : val)
214+ * this.left = (left===undefined ? null : left)
215+ * this.right = (right===undefined ? null : right)
216+ * }
217+ * }
218+ */
219+
220+ function pseudoPalindromicPaths(root : TreeNode | null ): number {
221+ const dfs = (root : TreeNode | null , mask : number ): number => {
222+ if (! root ) {
223+ return 0 ;
224+ }
225+ mask ^= 1 << root .val ;
226+ if (! root .left && ! root .right ) {
227+ return (mask & (mask - 1 )) === 0 ? 1 : 0 ;
228+ }
229+ return dfs (root .left , mask ) + dfs (root .right , mask );
230+ };
231+ return dfs (root , 0 );
232+ }
233+ ```
234+
235+ ### ** Rust**
236+
237+ ``` rust
238+ // Definition for a binary tree node.
239+ // #[derive(Debug, PartialEq, Eq)]
240+ // pub struct TreeNode {
241+ // pub val: i32,
242+ // pub left: Option<Rc<RefCell<TreeNode>>>,
243+ // pub right: Option<Rc<RefCell<TreeNode>>>,
244+ // }
245+ //
246+ // impl TreeNode {
247+ // #[inline]
248+ // pub fn new(val: i32) -> Self {
249+ // TreeNode {
250+ // val,
251+ // left: None,
252+ // right: None
253+ // }
254+ // }
255+ // }
256+ use std :: rc :: Rc ;
257+ use std :: cell :: RefCell ;
258+
259+ impl Solution {
260+ pub fn pseudo_palindromic_paths (root : Option <Rc <RefCell <TreeNode >>>) -> i32 {
261+ fn dfs (root : Option <Rc <RefCell <TreeNode >>>, mask : i32 ) -> i32 {
262+ if let Some (node ) = root {
263+ let mut mask = mask ;
264+ let val = node . borrow (). val;
265+ mask ^= 1 << val ;
266+
267+ if node . borrow (). left. is_none () && node . borrow (). right. is_none () {
268+ return if (mask & (mask - 1 )) == 0 { 1 } else { 0 };
269+ }
270+
271+ return (
272+ dfs (node . borrow (). left. clone (), mask ) + dfs (node . borrow (). right. clone (), mask )
273+ );
274+ }
275+ 0
276+ }
277+
278+ dfs (root , 0 )
279+ }
234280}
235281```
236282
0 commit comments