given
when
then
접근1) DFS
class Solution {
public boolean isSubPath(ListNode head, TreeNode root) {
if (root == null) return false;
return checkPath(root, head);
}
private boolean checkPath(TreeNode ndoe, ListNode head) {
if (node == null) return false;
// mathcing path is found
if (dfs(node, head)) return true;
return checkPath(node,left head) || checkPath(node.right, head);
}
private boolean dfs(TreeNode node, ListNode head) {
if (head==null) return true; // all nodes in the list matched
if (node==null) return false; // reached end of tree without matching all nodes
// value mismatch
if (node.val != head.val) return false;
return dfs(node.left, head.next) || dfs(node.right, head.next);
}
복잡도 진단
임의) n = 트리의 노드 수, n = 연결 리스트의 길이
- 시간 복잡도 O(n*m)
최악의 경우, 연결 리스트의 잠재적 시작점으로 트리의 모든 노드를 확인해야 할 수 있음
각 노드에 대해 연결 리스트의 최대 m개 노드를 탐색해야 할 수도 있음
- 공간 복잡도 O(n+m)
솔루션의 재귀적 특성으로 인해 공간 복잡도는 접근 방식 1과 동일하게 유지됨
--
접근2) 반복
- 재귀로 해결가능하다면 스택으로도 해결 가능
- 각 함수 호출이 호출 스택에 새 프레임을 추가하는 재귀와 달리 스택을 사용하면 재귀의 깊이가 너무 큰 경우(예: 매우 깊은 트리) 스택 오버플로 오류의 위험을 피할 수 있음
- 트리의 루트를 스택에 넣는 것으로 시작 -> 재귀 없이 트리 탐색하는데 도움됨
- 스택에서 맨 위 노드를 반복적으로 가져와 ...
뭐란겨
내 풀이
```java
// 이진 트리 root의 하위 경로를 형성하는지 boolean값을 return
class Solution {
public boolean isSubPath(ListNode head, TreeNode root) {
// 재귀 NullPointerException -> null 체크로 개선
if (root==null || root.left == null || root.right == null) return false;
boolean subLeft = head.next.equals(root.left);
boolean subRight = head.next.equals(root.right);
// root와 head의 val이 동일한 경우
if (head.val == root.val) {
// 하위 경로를 형성하면 true
if (subLeft || subRight && head == null ) { return true; }
// 아닌 경우 false
// if (!subLeft || !subRight) { return false; }
}
// // 특정 경로에서 하위 경로가 형성되는 경우 true return
if (subLeft || subRight) { return true; }
// if (!subLeft || !subRight) { return false; }
// 다음 head와 root 왼쪽 / 오른쪽 전달하며 재귀한다
return isSubPath(head.next, root.left) || isSubPath(head.next, root.right);
}
}
느낀점
많은 시간을 투자한 점
리팩토링
class Solution {
public boolean isSubPath(ListNode head, TreeNode root) {
if (root==null) return false;
if (checkPath(head, root)) return true;
return isSubPath(head, root.left) || isSubPath(head, root.right);
}
private boolean checkPath(ListNode head, TreeNode root) {
if (head == null) return true;
if (root == null || head.val != root.val) return false;
return checkPath(head.next, root.left) || checkPath(head.next, root.right);
}
}