1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Solution {
private int ans = 0;
private int oddCount = 0;

public int pseudoPalindromicPaths(TreeNode root) {
helper(root, new int[10]);
return ans;
}

private void helper(TreeNode node, int[] numCount) {
if (node == null) {
return;
}
int offset = numCount[node.val] % 2 == 1 ? -1 : 1;
numCount[node.val] += 1;
oddCount += offset;
helper(node.left, numCount);
helper(node.right, numCount);
if (node.left == null && node.right == null && oddCount <= 1) {
ans += 1;
}
numCount[node.val] -= 1;
oddCount -= offset;
}
}

用array记录每个数字出现的次数. post-order traversal(pre-order也可以). 我们是边走边记录从root到当前位置的node的path上node.val出现的频率. 到达leaf node的时候看是否最多只有一个num的频率是奇数次.

时间复杂度: O(9N) = O(N) 假设是个perfect tree, 那leaf node的个数与总共nodes的个数是一个数量级的, 因此是O(9N). 因为我们在leaf node要遍历数组.

空间复杂度: O(N) 递归需要用栈.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
private int ans = 0;

public int pseudoPalindromicPaths(TreeNode root) {
helper(root, 0);
return ans;
}

private void helper(TreeNode node, int path) {
if (node == null) {
return;
}
path ^= 1 << node.val;
helper(node.left, path);
helper(node.right, path);
if (node.left == null && node.right == null && (path & (path - 1)) == 0) {
ans += 1;
}
}
}

lee哥的解法使用一个integer来存1-9出现的次数. 偶数的话会抵消, 奇数的话, 对应的位置就是1. 那我们如何快速知道有奇数个1还是偶数个1? 好的方法就是num & (num - 1). 这个方法牢记.

有个问题是path更新完后, 为什么不返回原状? 因为这里path是local variable, 上一层保留了修改前的path的值. 因此就不需要我们把此时的path给改回去了.

时间复杂度: O(n)
空间复杂度: O(n)