Problem
Easy 문제입니다. (체감 난이도는 Medium 입니다)
이진 트리가 주어지고, root
부터 아래로 내려가면서 연속된 노드들의 합이 sum
이 되는 경우의 수를 구하는 문제입니다.
Solution 1
반드시 연속되야만 하기 때문에 연속되지 않은 값은 갖고 있을 필요가 없습니다.
예를 들면 root
가 10 이고 left
자식인 5 를 탐색해야 합니다.
5는 현재 자신의 값과 root
와의 합인 [5, 15]
와 sum
을 비교해야 합니다.
이걸 List
를 넘기는 대신에 10 을 더하는 경우, 더하지 않는 경우 두가지로 나누어서 호출하면 됩니다.
Java Code 1
class Solution {
public int pathSum(TreeNode root, int sum) {
if (root == null) return 0;
return pathSequenceSum(root, sum) + pathSum(root.left, sum) + pathSum(root.right, sum);
}
public int pathSequenceSum(TreeNode node, int sum) {
if (node == null) return 0;
int count = (sum == node.val) ? 1 : 0;
count += pathSequenceSum(node.left, sum - node.val) + pathSequenceSum(node.right, sum - node.val);
return count;
}
}
Solution 2
Discuss 에서는 HashMap
을 사용하여 O(n)
에 푸는 풀이가 있었습니다.
처음에는 이해를 잘 못했지만 차근차근 로그를 찍어가면서 확인해보니 어느정도 알 것 같았습니다.
HashMap
에다가 지금까지 지나온 노드들의 누적 합을 저장해두고 있는지 확인하면 됩니다.
예제를 보고 설명해보겠습니다. 위 Example 중에서 [10, 5, 3, 3]
만 본다고 생각합시다.
가장 끝의 자식노드인 3 에서 확인해야될 값은 [현재 노드의 값, 부모 노드부터 누적합, 조부모 노드부터 누적합... root 노드부터 현재까지 누적합]
이렇게 트리의 높이에 비례하여 비교해야될 값이 늘어나서 첫 풀이에는 List
를 넘겼었습니다.
이번에는 루트노드부터의 누적합을 HashMap
에 저장해두면 됩니다.
HashMap
은 { "누적합" : "갯수" }
형식으로 예제를 기준으로 {10 : 1, 15: 1, 18: 1, 21: 1}
이렇게 [10, 15, 18, 21]
이 한개씩 들어가있습니다.
그리고 누적합에서 target
넘버를 뺀 값이 map
에 존재한다면 현재 노드부터 루트 노드까지 연속된 노드들의 합 중에 일치하는 값이 있다는 뜻입니다.
마지막 노드인 3 에서 가능한 sum
의 경우는 [21, 11, 6, 3]
입니다.
현재 노드까지의 누적합 21 에서 [21, 11, 6, 3]
을 빼면 [0, 10, 15, 18]
입니다.
HashMap
에 들어있는 값과 똑같지 않나요?
마지막 노드까지 나올 수 있는 연속합들을 한번에 비교할 수 있습니다.
근데 map
에 0은 없는데 어디서 넣을까요?
root
부터 현재 노드까지 더한 경우가 sum
이 될 수도 있기 때문에 처음에 {0: 1}
을 넣고 시작합니다.
그림 없이 설명하려니 좀 힘들 수가 있는데 코드를 보면 더 이해하기 쉬울 수도 있습니다.
Java Code 2
class Solution {
public int pathSum(TreeNode root, int sum) {
HashMap<Integer, Integer> map = new HashMap<>();
map.put(0, 1);
return recursive(root, 0, sum, map);
}
public int recursive(TreeNode node, int accumulateSum, int sum, HashMap<Integer, Integer> map) {
if (node == null) return 0;
accumulateSum += node.val;
int count = map.getOrDefault(accumulateSum - sum, 0);
map.put(accumulateSum, map.getOrDefault(accumulateSum, 0) + 1);
count += recursive(node.left, accumulateSum, sum, map) + recursive(node.right, accumulateSum, sum, map);
map.put(accumulateSum, map.get(accumulateSum) - 1);
return count;
}
}
'알고리즘 문제 > LeetCode' 카테고리의 다른 글
[LeetCode Easy] Single Number (Java, Kotlin) (0) | 2019.12.11 |
---|---|
[LeetCode Easy] Maximum Depth Of Binary Tree (Java, Kotlin) (0) | 2019.12.02 |
[LeetCode Medium] Add Two Numbers (Java) (0) | 2019.11.24 |
[LeetCode Medium] Combination Sum (Java) (0) | 2019.11.24 |
[LeetCode Medium] 3Sum (Java) (0) | 2019.11.23 |