|
| 1 | +# Intuition |
| 2 | +n번 째를 알기 위해 정보(몇 번째에 어떤 요소가 있는지)를 알아야 한다. |
| 3 | +# Approach |
| 4 | +1. 배열에 링크드 리스트 정보를 모두 넣는다. |
| 5 | +2. 맨 앞 요소를 제거해야하는 경우 (`len(nodes) == n`) 헤드의 다음을 반환한다. |
| 6 | +3. 뒤에서 `n`번째 요소(`len(nodes)-n`)의 앞과 뒤를 이어붙여 `n`번째 요소를 제거한다. |
| 7 | +# Complexity |
| 8 | +- Time complexity: $O(n)$ |
| 9 | + - 링크드 리스트의 길이 `n`에 대하여, 이를 순회하는 비용이 발생한다. |
| 10 | +- Space complexity: $O(n)$ |
| 11 | + - 링크드 리스트의 길이 `n`에 대하여, 배열의 크기 `n`이 발생한다. |
| 12 | + |
| 13 | +# Code |
| 14 | +## Array |
| 15 | +```go |
| 16 | +func removeNthFromEnd(head *ListNode, n int) *ListNode { |
| 17 | + nodes := make([]*ListNode, 0, 100) |
| 18 | + |
| 19 | + for curr := head; curr != nil; curr = curr.Next { |
| 20 | + nodes = append(nodes, curr) |
| 21 | + } |
| 22 | + |
| 23 | + if len(nodes) == n { |
| 24 | + return head.Next |
| 25 | + } |
| 26 | + |
| 27 | + nodes[len(nodes)-n-1].Next = nodes[len(nodes)-n].Next |
| 28 | + return head |
| 29 | +} |
| 30 | + |
| 31 | +``` |
| 32 | +# Intuition |
| 33 | +배열의 모든 원소를 저장할 필요는 없어 보였다. 공간 복잡도를 줄일 방법을 알아보았다. |
| 34 | +# Approach |
| 35 | +모든 원소가 아니라, `n`번째의 이전(`prev`), 이후 (`next`)만을 저장하게 하였다. |
| 36 | +# Complexity |
| 37 | +- Time complexity: $O(n)$ |
| 38 | + - 링크드 리스트의 길이 `n`에 대하여, 이를 순회하는 비용이 발생한다. |
| 39 | +- Space complexity: $O(1)$ |
| 40 | + - 2개의 요소만 유지하므로, `O(1)`이다. |
| 41 | + |
| 42 | +# Code |
| 43 | +## Two Pointer |
| 44 | +```go |
| 45 | +func removeNthFromEnd(head *ListNode, n int) *ListNode { |
| 46 | + len := 0 |
| 47 | + for curr := head; curr != nil; curr = curr.Next { |
| 48 | + len++ |
| 49 | + } |
| 50 | + |
| 51 | + if len == n { |
| 52 | + return head.Next |
| 53 | + } |
| 54 | + |
| 55 | + var prev, curr, next *ListNode |
| 56 | + curr = head |
| 57 | + next = head.Next |
| 58 | + for i := 0; i+n < len; i++ { |
| 59 | + prev = curr |
| 60 | + curr = next |
| 61 | + next = next.Next |
| 62 | + } |
| 63 | + |
| 64 | + prev.Next = next |
| 65 | + return head |
| 66 | +} |
| 67 | + |
| 68 | +``` |
0 commit comments