Skip to content

206. Reverse Linked List #8

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
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
127 changes: 127 additions & 0 deletions lc206.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
"""step1
単純にポインタの付け替えをすれば良さそう。
手がつけられなかった。わからなかった点としては、どうやって最後の要素(tail)にアクセスするのかと、そこから逆向きに動かす操作方法がわからなかった。解答を見てなんとなくの理解をした(手を動かして実際に操作することまでわかったが、感覚的に掴めていない)。
"""

class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
node = None

while head:
temp = head.next
head.next = node
node = head
head = temp

return node

"""step2
Discordを遡ってみて、参考にしたPRを以下に記します。
https://github.com/ichika0615/arai60/pull/6#discussion_r1864910519
https://github.com/katataku/leetcode/pull/7#discussion_r1860201328
https://github.com/konnysh/arai60/pull/7#discussion_r1845699956
https://github.com/tarinaihitori/leetcode/pull/6#issuecomment-2439783292



この問題の解き方は以下の方法がありそう
1. スタックで繋ぎ変え
class Solution:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

レビューわーにとって読みやすくるため、シンタックスハイライトが有効になるような書き方をしていただけるとありがたいです。

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

承知しました、次回以降別の書き方にしてみます

def reverseList(self, head: [Optional[ListNode]) -> Optional[ListNode]:
stack = []
Copy link

@ichika0615 ichika0615 Dec 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

データ構造の名前をそのまま命名に使うと読みにくくなる気がしました。found_nodesとかnodesとかいいかもです

current = head
while current:
stack.append(current)
curent = current.next

if not stack:
return None
reversed_head = stack.pop()
current = reversed_head

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

currentが違う文脈で2回登場するのが読みづらいかもしれません。最初のcurrentはオリジナルの連結リストを走査するのに使って、次のcurrentはリバースされた連結リストのノードのことを指していると思います。私はnode_in_originalnode_in_reversedなどを使ってました。


while stack:
current.next = stack.pop()
current = current.next
current.next = None

return reversed_head
時間計算量: O(n), 空間計算量: O(n)
愚直なやり方、

2. スタックなしで繋ぎ変え
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
reversed_node = None
current = head

while current:
next_node = current.next
current.next = reversed_node
reversed_node = current
current = next_nodd

return reversed_node

時間計算量: O(n), 空間計算量: O(n)
step1の変数を変えた改良版、headは動かさないようにしている。また、reversed_nodeと変数名をつけることで逆側からのという問題の文脈を付け加えた。

3. 再帰

class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
if head is None or head.next is None:
return head
new_head = self.reverseList(head.next)
head.next.next = head
head.next = None
Comment on lines +74 to +76
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

これ、私は先に一回切断したほうが理解はしやすいと思います。

tail = head.next
head.next = None
new_head = self.reverseList(tail)
# tail is now the last node of the reversed list.
tail.next = head

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

確かにtailを使って書いた方がhead.next.nextみたいなことを書かなくて良いので読みやすいですね


return new_head


4. 逆向きの再帰

class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
def _reverse_linked_list(head, previous):
if head is None:
return previous
temp = head.next
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

関数にも渡す値となると、命名はtempじゃないほうがよいと思いました。
tempの使いどきは、変数のswapのようなレベルで値を一時保存するときだけの印象があります。

head.next = previous
return _reverse_linked_list(temp, head)

retrun _reverse_linked_list(head, None)

個人的には3.の再帰よりもこちらの方が2番のやり方に近いと感じていて、分かりやすい。


再帰で解く時は、recursionErrorと呼ばれるエラーが発生する可能性があるので常にそれを意識する 
"""

"""step3

1分30秒
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
current = head
reverse_node = None

while current:
next_node = current.next
current.next = reverse_node
reverse_node = current
current = next_node

return reverse_node

4分
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
def _reverse_linked_list(head, previous):
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inner function の関数名の先頭には _ を付けなくてよいみたいです。

katataku/leetcode#4 (comment)

if head is None:
return previous
next_node = head.next
head.next = previous
return _reverse_linked_list(next_node, head)

return _reverse_linked_list(head, None)
"""