54
54
55
55
<!-- 这里可写通用的实现逻辑 -->
56
56
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$ 是二叉树的节点数。
58
76
59
77
<!-- tabs:start -->
60
78
70
88
# self.left = left
71
89
# self.right = right
72
90
class 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 ):
75
93
if root is None :
76
- return
77
- nonlocal ans, counter
78
- counter[root.val] += 1
94
+ return 0
95
+ mask ^= 1 << root.val
79
96
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 )
91
101
```
92
102
93
103
### ** Java**
@@ -111,40 +121,19 @@ class Solution:
111
121
* }
112
122
*/
113
123
class Solution {
114
- private int ans;
115
- private int [] counter;
116
-
117
124
public int pseudoPalindromicPaths (TreeNode root ) {
118
- ans = 0 ;
119
- counter = new int [10 ];
120
- dfs(root);
121
- return ans;
125
+ return dfs(root, 0 );
122
126
}
123
127
124
- private void dfs (TreeNode root ) {
128
+ private int dfs (TreeNode root , int mask ) {
125
129
if (root == null ) {
126
- return ;
130
+ return 0 ;
127
131
}
128
- ++ counter[ root. val] ;
132
+ mask ^ = 1 << root. val;
129
133
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 ;
146
135
}
147
- return n < 2 ;
136
+ return dfs(root . left, mask) + dfs(root . right, mask) ;
148
137
}
149
138
}
150
139
```
@@ -165,30 +154,18 @@ class Solution {
165
154
*/
166
155
class Solution {
167
156
public:
168
- int ans;
169
- vector<int > counter;
170
-
171
157
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);
192
169
}
193
170
};
194
171
```
@@ -205,32 +182,101 @@ public:
205
182
* }
206
183
*/
207
184
func 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 {
212
187
if root == nil {
213
- return
188
+ return 0
214
189
}
215
- counter[ root.Val]++
190
+ mask ^= 1 << root.Val
216
191
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
225
194
}
226
- } else {
227
- dfs(root.Left)
228
- dfs(root.Right)
195
+ return 0
229
196
}
230
- counter[ root.Val]--
197
+ return dfs( root.Left, mask) + dfs(root.Right, mask)
231
198
}
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
+ }
234
280
}
235
281
```
236
282
0 commit comments