Python Algorithm Q15
Q15 Reverse Linked List
Q
Given the head
of a singly linked list, reverse the list, and return the reversed list.
Sample Input
Input: head = [1,2,3,4,5]
Output: [5,4,3,2,1]
Input: head = [1,2]
Output: [2,1]
Input: head = []
Output: []
Constraints
- The number of nodes in the list is the range [0, 5000].
- -5000 <= Node.val <= 5000
1. My Own Solution
1
2
3
4
5
6
7
8
9
10
11
12
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
node = head #the list to reverse
rev = None # the space that reversed list is saved
while node:
rev, rev.next, node = node, rev, node.next
return rev
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#to test, you have to make to linked-list manually.
inp = [1, 3, 5, 9]
list4 = ListNode(inp[3], None)
list3 = ListNode(inp[2], list4)
list2 = ListNode(inp[1], list3)
list1 = ListNode(inp[0], list2)
#for test
a = Solution()
new_head = a.reverseList(list1)
while new_head:
print(new_head.val)
Trained with the crazy #13 problem, this question is too easy to me. But for the further time, I’ll write description for this solution. I fully utilizied multi-assignment in python, to prevent unnecessary use of memory.
- Assign “head” to “node”. Then make empty list(=None) named rev.
- Multi-Assign variables. Assign current node to the rev. Then by rev.next = rev, rev points the previous rev. Lastly, node moves to the next node.
** 2번에 대한 보충 설명 : 반복해서 언급하지만, multi-assignment는 그 연산 과정의 특징에 의해 여러 줄로 나눠서 할당했을 때와 다른 결과를 보인다.
1
2
3
4
5
6
A = node
B = rev
C = node.next
rev = A
rev.next = B
node = C
이런 식으로 계산되기 때문에 A, B를 계산할 때 예상이랑 다른 과정을 거치게 된다. rev에 먼저 node를 그대로 할당한다. 다음 “현재” 노드, 즉 방금 node를 막 할당한 그 rev가 가르키는 다음 주소 rev.next에 이전 rev를 넣는다. 따라서 rev는 할당하기 이전의 rev를 가르키게 된다.
2. Given Solution #1
1
2
3
4
5
6
7
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
node, rev = head, None
while node:
next, node.next = node.next, rev
rev, node = node, next
return rev
[Using Iteration]
Perfectly same as my solution, but the variable “next” is additionally used.
3. Given Solution #2
1
2
3
4
5
6
7
8
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
def reverse(node: ListNode, prev: ListNode = None):
if not node:
return prev
next, node.next = node.next, prev
return reverse(next, node)
return reverse(head)
[Using Recursion]
Not that hard. Just as complicated as the recursion problem usually does. Let’s explain it shortly.
- Loop ends when node is None. All other cases infinitely loops. You can describe the code simply like this.
1
2
3
4
def reverse(~):
def reverseList( ):
return reverse(head)
- until node reaches None, it keeps assigning
next, node.next = node.next, prev
. “Next” is the following node of the current node. And by the codenode.next = prev
, the current node points the previous node. Then, repeat it by assigning next to the node, node to the prev.
** 2번에 대한 보충 설명 : 이 코드를 따라 그림을 그리다 보면 이 코드는 node를 하나씩 뒤로 밀고, 현재 노드가 가르키는 화살표의 방향을 정 반대로 돌리는 코드이다. 2번이 설명하는 것을 풀어서 설명하면, node가 none이 되어 재귀가 끝나기 전까지 계속 반복해서 다중 할당을 진행한다. next라는 변수가 현재 노드의 다음 노드를 가르키게 한다. 그 후, 현재 노드의 다음 주소를 prev으로 바꿔서 node가 이전 방향을 가르키게 한다.

Python MEMO의 linked_list 포스팅에 있는 gif를 참고하면 좀 더 쉽게 구조가 이해가 될 것이다.
마지막에 가서는 prev는 원래 연결 리스트의 맨끝을 가르키게 되는데, prev는 원래 연결 리스트의 역방향 연결 리스트이므로 거꾸로 head를 가르키게 된다. 따라서 point를 사전에 지정해놓거나 할 필요 없이 prev를 return하면 head_node를 구할 수 있다.
Overall Review
Pretty Easy. I merely felt some achievement after solving and understanding this question.