Skip to content

Commit 67e06dd

Browse files
authored
feat: add solutions to lc problem: No.1457 (doocs#2004)
No.1457.Pseudo-Palindromic Paths in a Binary Tree
1 parent 0fa1357 commit 67e06dd

File tree

8 files changed

+419
-307
lines changed

8 files changed

+419
-307
lines changed

solution/1400-1499/1457.Pseudo-Palindromic Paths in a Binary Tree/README.md

+133-87
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,25 @@
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

@@ -70,24 +88,16 @@
7088
# self.left = left
7189
# self.right = right
7290
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):
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
*/
113123
class 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
*/
166155
class Solution {
167156
public:
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
*/
207184
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 {
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

Comments
 (0)