Skip to content

Commit 570e44a

Browse files
authored
Merge pull request #2258 from radiantchoi/main
[radiantchoi] WEEK 09 Solutions
2 parents 6727b0b + d558087 commit 570e44a

2 files changed

Lines changed: 128 additions & 0 deletions

File tree

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/**
2+
* Definition for singly-linked list.
3+
* public class ListNode {
4+
* public var val: Int
5+
* public var next: ListNode?
6+
* public init(_ val: Int) {
7+
* self.val = val
8+
* self.next = nil
9+
* }
10+
* }
11+
*/
12+
13+
// 1차 버전: 문제의 constraint에 따라 1만 번의 traverse를 수행하는 답안 (통과는 됩니다)
14+
class Solution {
15+
func hasCycle(_ head: ListNode?) -> Bool {
16+
guard let head else { return false }
17+
18+
return traverse(head, 0)
19+
}
20+
21+
func traverse(_ node: ListNode?, _ currentIndex: Int) -> Bool {
22+
guard let node else { return false }
23+
guard currentIndex < 10000 else { return true }
24+
25+
return traverse(node.next, currentIndex + 1)
26+
}
27+
}
28+
29+
// LLM 첨삭 버전: Floyd's Cycle Detection Algorithm 사용
30+
class Solution {
31+
func hasCycle(_ head: ListNode?) -> Bool {
32+
guard let head else { return false }
33+
34+
var slow: ListNode? = head
35+
var fast: ListNode? = head
36+
37+
while true {
38+
// fast는 한 번에 두 칸씩 이동
39+
fast = fast?.next?.next
40+
41+
// slow는 한 번에 한 칸씩 이동
42+
slow = slow?.next
43+
44+
// fast나 slow가 nil이면 cycle이 없다
45+
if fast == nil || slow == nil { return false }
46+
47+
// fast와 slow가 같은 노드를 가리키면 cycle이 있다
48+
// break로 마무리한 이유는, 그래서 그 만나는 노드가 어디인가? 라는 문제에 응용하기 위함
49+
if fast === slow { break }
50+
}
51+
52+
// 사이클 시작 지점을 찾는 문제일 경우 여기에 entry 포인터 삽입 후 탐색
53+
54+
return true
55+
}
56+
}
57+
58+
/*
59+
사이클 시작 지점을 찾으시오, 라는 문제일 경우?
60+
entry라는 별도의 포인터를 하나 더 둔 다음 slow와 함께 한 칸씩 이동시킨다.
61+
두 포인터가 만나는 지점이 사이클 시작 지점!
62+
이것이 가능한 이유는, 아래의 이동 거리 공식 때문에 그렇다.
63+
64+
L: 사이클 입구까지의 길이
65+
C: 사이클 길이
66+
d: 사이클 내에서, 사이클 종료(==시작)까지 남은 거리
67+
68+
fast의 이동 거리: L + n * C + d
69+
slow의 이동 거리: L + d
70+
71+
fast의 이동 거리는 slow의 이동 거리의 2배이므로
72+
2 * (L + d) = L + n * C + d
73+
74+
따라서, L = n * C - d 이다.
75+
그리고 L은 entry 포인터가 이동해야 하는 거리이다.
76+
n * C - d는 사이클 안에서는 C - d와 같다. fast 노드가 n번 돌았을 뿐, 사이클 안이었기 때문.
77+
따라서 entry 포인터와 slow 포인터를 다시 한 칸씩 이동시키다 보면, 반드시 만나게 된다.
78+
이 만나는 지점이 사이클 시작 지점.
79+
*/
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// 힌트를 받은 아이디어: 특정 칸에서 흘러내려가는 것이 아니라, 바다에서부터 거슬러 올라가는 것을 계산하면 어떨까?
2+
3+
class Solution {
4+
func pacificAtlantic(_ heights: [[Int]]) -> [[Int]] {
5+
var result = [[Int]]()
6+
var pacificMap = Array(repeating: Array(repeating: false, count: heights[0].count), count: heights.count)
7+
var atlanticMap = Array(repeating: Array(repeating: false, count: heights[0].count), count: heights.count)
8+
9+
for k in 0..<heights[0].count {
10+
traverse(heights, 0, k, 0, &pacificMap)
11+
}
12+
13+
for l in 0..<heights.count {
14+
traverse(heights, l, 0, 0, &pacificMap)
15+
}
16+
17+
for m in 0..<heights[0].count {
18+
traverse(heights, heights.count - 1, m, 0, &atlanticMap)
19+
}
20+
21+
for n in 0..<heights.count {
22+
traverse(heights, n, heights[0].count - 1, 0, &atlanticMap)
23+
}
24+
25+
for i in 0..<heights.count {
26+
for j in 0..<heights[i].count {
27+
if pacificMap[i][j] && atlanticMap[i][j] {
28+
result.append([i, j])
29+
}
30+
}
31+
}
32+
33+
return result
34+
}
35+
36+
func traverse(_ heights: [[Int]], _ row: Int, _ col: Int, _ previous: Int, _ reachabilities: inout [[Bool]]) {
37+
guard (0..<heights.count) ~= row && (0..<heights[0].count) ~= col else { return }
38+
39+
guard heights[row][col] >= previous else { return }
40+
guard !reachabilities[row][col] else { return }
41+
42+
reachabilities[row][col] = true
43+
44+
traverse(heights, row - 1, col, heights[row][col], &reachabilities)
45+
traverse(heights, row + 1, col, heights[row][col], &reachabilities)
46+
traverse(heights, row, col - 1, heights[row][col], &reachabilities)
47+
traverse(heights, row, col + 1, heights[row][col], &reachabilities)
48+
}
49+
}

0 commit comments

Comments
 (0)