Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
189 changes: 189 additions & 0 deletions 206. Reverse Linked List/206. Reverse Linked List.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
https://leetcode.com/problems/reverse-linked-list/description/

Given the head of a singly linked list, reverse the list, and return the reversed list.

Example 1:


Input: head = [1,2,3,4,5]
Output: [5,4,3,2,1]
Example 2:


Input: head = [1,2]
Output: [2,1]
Example 3:

Input: head = []
Output: []


Constraints:

The number of nodes in the list is the range [0, 5000].
-5000 <= Node.val <= 5000


Follow up: A linked list can be reversed either iteratively or recursively. Could you implement both? 

## STEP 1
### stack
Arai 60の分野で言うとstackで分類されていたのでstackで書いてみる。
```python
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
if head is None or head.next is None:
return head
visited_nodes = []
node = head
while node is not None:
visited_nodes.append(node)
node = node.next
new_head = visited_nodes.pop()
node = new_head
while visited_nodes:
node.next = visited_nodes.pop()
node = node.next
node.next = None
return new_head
```

### recursive
多分再帰でも解けそう?と思ったのでイメージしてみる。
まずbase caseを考える。
nodeが単体、つまりnode.nextがない場合、素直にnodeを返す。
次にinductive stepを考える。
reverseList()で返ってきた配列はすでにひっくり返っていて、それにどうやって連結するかイメージする。1 -> 2 -> 3 -> 4 -> 5 の例だと 1 -> 2 の1を今持ってて再帰で返ってきたのは 2 <- 3 <- 4 <- 5の5の部分。返ってきたやつの2のnodeの次に1をくっつけたい。素直に返ってきたものをまた遡ると時間がかるけど、この2は今持ってる1のnextでもあるから1のnextのnextを1にするというちょっと循環っぽい見た目のことをやると連結できて、で今の1のnextをNoneにすれば循環しなくなる。終わったら5の部分を返す。
例外としてNoneが来たときはそのままNoneを返したいのでbase caseの時にまとめて処理しておくので大丈夫そう。これをコードに起こしていく。
```python
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
if head is None or head.next is None:
return head
reversed_nodes = self.reverseList(head.next)
head.next.next = head
head.next = None
return reversed_nodes
```


### iterative
iterativeでも解けるはずなんだけど。ちょっと頭の中だけではイメージするのが苦手なのでお絵描き。本番も実地だったらホワイトボードに書かせてもらえるんだけどどうなんだろう?オンラインの時も何かかけるものを用意しておいて見せればいいんだろうか。

```python
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
prev_node = None
node = head
while node is not None:
next_node = node.next
node.next = prev_node
prev_node = node
node = next_node
return prev_node
```

## STEP 2

### stack
変数の名前をちょっと修正。
```python
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
if head is None:
return head
stacked_nodes = []
node = head
while node is not None:
stacked_nodes.append(node)
node = node.next
new_head = stacked_nodes.pop()
node = new_head
while stacked_nodes:
node.next = stacked_nodes.pop()
node = node.next
node.next = None
return new_head
```

### recursive
ログを色々と読んだが、再帰の時に頭と尻尾が欲しいんだったら最初から渡せば良い。つながったままひっくり返すのを考えるのは難しいから先に切ってひっくり返した後またくっつける方が楽。という発想はあんまりなかった。本番の緊張を考えればこういう方法で一旦書いてしまった方が初めから綺麗に書こうとして書けなくて時間を空費するリスクを抑えられると思った。書いてみた後にうまい最適化を思いつくかもしれない。

```python
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
def recursive_reverse(node):
if node is None or node.next is None:
return node, node
to_reversed_head = node.next
node.next = None
yet_reversed_node = node
reversed_head, reversed_tail = recursive_reverse(to_reversed_head)
reversed_tail.next = yet_reversed_node
return reversed_head, yet_reversed_node
reversed_head, reversed_tail = recursive_reverse(head)
```

### iterative
改善点は特に思いつかない。
```python
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
prev_node = None
node = head
while node is not None:
next_node = node.next
node.next = prev_node
prev_node = node
node = next_node
return prev_node
```

### STEP 3
stackの方は別にいいかと思ったのでiterativeとrecursiveを2種類練習。
### iterative
```python
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
prev_node = None
node = head
while node is not None:
next_node = node.next
node.next = prev_node
prev_node = node
node = next_node
return prev_node
```

### recursive
```python
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
def reverse_recursively(node):
if node is None or node.next is None:
return node, node
reversing_head = node.next
node.next = None
yet_reversed_node = node
reversed_head, reversed_tail = reverse_recursively(reversing_head)
reversed_tail.next = yet_reversed_node
return reversed_head, yet_reversed_node
reversed_head, reversed_tail = reverse_recursively(head)
return reversed_head
```

```python
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
if head is None or head.next is None:
return head
reversed_head = self.reverseList(head.next)
head.next.next = head
head.next = None
return reversed_head
```