LeetCode 666. Path Sum IV
2020-05-21 17:42:41 # leetcode

Problem

LeetCode 666. Path Sum IV

1. 题目简述

如果一棵树的高度不超过5,则这棵树可以被表示为一列三位数字的数组(数组从小到大排列),对于每位数字都有其表示的含义:

  1. 百位D表示该节点的深, 1 <= D <= 4
  2. 十位P表示这个数字在该层的位置,1 <= P <= 8
  3. 个位V表示该节点的值,0 <= V <= 9

求所有的从root到leaf的路径和。例如:

Input: [113, 215, 221]
Output: 12
Explanation: 
The tree that the list represents is:
    3
   / \
  5   1

The path sum is (3 + 5) + (3 + 1) = 12.

2. 算法思路

DFS

此题的算法并不难,之前也有算过类似的题目,难点在于如何将一棵树完整地复原。一种做法是自己定义TreeNode,然后完整复原整棵树;另一种是使用HashMap来巧妙存储树,用HashMap的时候,前两位为key,个位为value,D和P加在一起能够唯一确定一个节点,且其子节点和右节点的key也能过通过数学公式算出来;第三种就是使用数组来储存,因为高度最高也就是4,建立一个二维数组来存储。

3. 解法

  1. 自己定义TreeNode来存储,然后遍历
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

class Solution {

class Node {
Node left, right;
int val;
Node(int v) {val = v;
}

int res = 0;
public int pathSum(int[] nums) {
Node root = new Node(nums[0] % 10);

// 这个构建方法中,判断左右子树那块没太搞懂,直接抄了
for (int num: nums) {
if (num == nums[0]) continue;
int depth = num / 100, pos = num / 10 % 10, val = num % 10;
pos--;
Node cur = root;
for (int d = depth - 2; d >= 0; --d) {
if (pos < 1<<d) {
if (cur.left == null) cur.left = new Node(val);
cur = cur.left;
} else {
if (cur.right == null) cur.right = new Node(val);
cur = cur.right;
}
pos %= 1<<d;
}
}

dfs(root, 0);
return res;
}

private void dfs(TreeNode root, int currSum) {
if (root == null) {
return;
}

currSum += root.val;
if (root.left == null && root.right == null) {
res += currSum;
return;
}

dfs(root.left, currSum);
dfs(root.right, currSum);
}
}


  1. 使用HashMap来遍历整棵树(直接抄了solution)
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
26
27
28
29

class Solution {
int ans = 0;
Map<Integer, Integer> values;
public int pathSum(int[] nums) {
values = new HashMap();
for (int num: nums)
values.put(num / 10, num % 10);

dfs(nums[0] / 10, 0);
return ans;
}

public void dfs(int node, int sum) {
if (!values.containsKey(node)) return;
sum += values.get(node);

int depth = node / 10, pos = node % 10;
int left = (depth + 1) * 10 + 2 * pos - 1;
int right = left + 1;

if (!values.containsKey(left) && !values.containsKey(right)) {
ans += sum;
} else {
dfs(left, sum);
dfs(right, sum);
}
}
}
  1. 我的原始做法,使用数组来存储
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
26
27
28
29
30
31
32
33
34
35
36
class Solution {
int res = 0;
public int pathSum(int[] nums) {
int[][] tree = new int[4][];

for (int i = 0; i < 4; i++) {
tree[i] = new int[(int)Math.pow(2, i)];
Arrays.fill(tree[i], -1);
}

for (int x : nums) {
int d = x / 100;
int p = (x % 100) / 10;
int v = x % 10;
tree[d - 1][p - 1] = v;
}

dfs(tree, 0, 0, 0);

return res;
}

private void dfs(int[][] tree, int d, int p, int sum) {
if (d >= 4 || p >= (int)Math.pow(2, d) || tree[d][p] == -1) {
return;
}
sum += tree[d][p];
if (d == 3 || (tree[d + 1][2 * p] == -1 && tree[d + 1][2 * p + 1] == -1)) {
res += sum;
return;
}
dfs(tree, d + 1, 2 * p, sum);
dfs(tree, d + 1, 2 * p + 1, sum);
}
}