Skip to content

Commit 62f8abf

Browse files
committed
solve(w12): 19. Remove Nth Node From End of List
1 parent 343ec33 commit 62f8abf

File tree

1 file changed

+102
-0
lines changed

1 file changed

+102
-0
lines changed
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
# https://leetcode.com/problems/remove-nth-node-from-end-of-list/
2+
3+
from typing import Optional
4+
5+
# Definition for singly-linked list.
6+
class ListNode:
7+
def __init__(self, val=0, next=None):
8+
self.val = val
9+
self.next = next
10+
11+
class Solution:
12+
def removeNthFromEnd_recur(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
13+
"""
14+
[Complexity]
15+
- TC: O(len)
16+
- SC: O(len) (call stack)
17+
18+
[Approach]
19+
재귀적으로 linked list를 확인하며 끝에서부터의 순서를 확인 후, 다음 node의 순서가 n과 같을 때 다음 node를 건너뛰도록 한다.
20+
head node를 제거해야 하는 경우(= 끝에서부터 n번째인 node가 head인 경우)에는, 재귀 함수 내에서 node 제거가 불가능하므로 head.next를 반환한다.
21+
"""
22+
23+
def check_order_from_end(curr):
24+
# base condition
25+
if not curr.next:
26+
return 1
27+
28+
# recur
29+
next_order_from_end = check_order_from_end(curr.next)
30+
# nth from end인 node를 건너뛰기
31+
if next_order_from_end == n:
32+
curr.next = curr.next.next
33+
34+
return next_order_from_end + 1
35+
36+
# head node를 제거해야 하는 경우라면, check_order_from_end() 내에서 node 제거가 불가능하므로 head.next를 반환해야 함
37+
if check_order_from_end(head) == n:
38+
return head.next
39+
40+
return head
41+
42+
def removeNthFromEnd_recur2(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
43+
"""
44+
[Complexity]
45+
- TC: O(len)
46+
- SC: O(len) (call stack)
47+
48+
[Approach]
49+
이전 풀이에서 head node를 제거해야 하는 경우를 따로 처리하지 않으려면, 주어진 head를 가리키는 dummy node(= prev)를 추가하고
50+
dummy node의 next node를 반환하면 된다.
51+
"""
52+
53+
def check_order_from_end(curr):
54+
# base condition
55+
if not curr.next:
56+
return 1
57+
58+
# recur
59+
next_order_from_end = check_order_from_end(curr.next)
60+
# nth from end인 node를 건너뛰기
61+
if next_order_from_end == n:
62+
curr.next = curr.next.next
63+
64+
return next_order_from_end + 1
65+
66+
prev = ListNode(next=head)
67+
check_order_from_end(prev)
68+
69+
return prev.next
70+
71+
def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
72+
"""
73+
[Complexity]
74+
- TC: O(len)
75+
- SC: O(1)
76+
77+
[Approach]
78+
slow, fast의 two pointer를 이용해 반복문으로 풀 수 있다.
79+
1. fast를 n 번 전진
80+
2. fast가 끝에 도달한 경우, 첫 번째 node를 제거해야하므로 head.next 반환
81+
3. 현재 fast의 위치에서 slow와 fast를 함께 전진하면, fast가 끝에 도달할 때 slow는 뒤에서부터 n + 1번째 node임
82+
4. 뒤에서부터 n + 1번째인 node가 n - 1번째 node를 가리키도록 함
83+
"""
84+
slow = fast = head
85+
86+
# 1. fast를 n 번 전진
87+
for _ in range(n):
88+
fast = fast.next
89+
90+
# 2. fast가 끝에 도달한 경우, 첫 번째 node를 제거해야하므로 head.next 반환
91+
if not fast:
92+
return head.next
93+
94+
# 3. 현재 fast의 위치에서 slow와 fast를 함께 전진하면,
95+
# fast가 끝에 도달할 때 slow는 뒤에서부터 n + 1번째 node임
96+
while fast.next:
97+
slow, fast = slow.next, fast.next
98+
99+
# 4. 뒤에서부터 n + 1번째인 node가 n - 1번째 node를 가리키도록 함
100+
slow.next = slow.next.next
101+
102+
return head

0 commit comments

Comments
 (0)