Skip to content
Open
Show file tree
Hide file tree
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
28 changes: 28 additions & 0 deletions 0138.Copy-List-with-Random-Pointer/memo.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# 138. Copy List with Random Pointer

## step1

頭から実装するとstep1.pyとなった。

同じ処理が現れたので関数化したが、getattrなどが何度も現れてわかりづらい

## step2

ソリューションを漁る

https://leetcode.com/problems/copy-list-with-random-pointer/solutions/379056/python-solution-with-comments-on-using-a-xf3k/?envType=problem-list-v2&envId=7p5x763

再帰を使うのは思いつかなかった
```python
def copyRandomList(self, head: 'Optional[Node]', seen={None: None}) -> 'Optional[Node]':
""" O(N)TS """
if head not in seen:
seen[head] = Node(head.val)
seen[head].next = self.copyRandomList(head.next, seen)
seen[head].random = self.copyRandomList(head.random, seen)
return seen[head]
```

https://leetcode.com/problems/copy-list-with-random-pointer/solutions/7052593/on-and-o1-solutions-by-russelldcosta-lbh8/?envType=problem-list-v2&envId=7p5x763

Hashmapを使わずに解ける。空間計算量がO(1)になる。
36 changes: 36 additions & 0 deletions 0138.Copy-List-with-Random-Pointer/step1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"""
# Definition for a Node.
"""


class Node:
def __init__(self, x: int, next: "Node" = None, random: "Node" = None):
self.val = int(x)
self.next = next
self.random = random


class Solution:
def copyRandomList(self, head: Node | None) -> Node | None:
if head is None:
return head
copy_head = Node(x=head.val)
original_to_copy = {head: copy_head}
node = head
node_copy = copy_head
while node is not None:
if node.next is not None:
if node.next in original_to_copy:
node_copy.next = original_to_copy[node.next]
else:
node_copy.next = Node(x=node.next.val)
original_to_copy[node.next] = node_copy.next
if node.random is not None:
if node.random in original_to_copy:
node_copy.random = original_to_copy[node.random]
else:
node_copy.random = Node(x=node.random.val)
original_to_copy[node.random] = node_copy.random
node = node.next
node_copy = node_copy.next
return copy_head
42 changes: 42 additions & 0 deletions 0138.Copy-List-with-Random-Pointer/step1_revised.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"""
# Definition for a Node.
"""


class Node:
def __init__(self, x: int, next: "Node" = None, random: "Node" = None):
self.val = int(x)
self.next = next
self.random = random


class Solution:
def copyRandomList(self, head: Node | None) -> Node | None:
if head is None:
return head

copy_head = Node(x=head.val)
original_to_copy = {head: copy_head}
node = head
node_copy = copy_head

def update_attribute(node: Node, node_copy: Node, attribute: str) -> None:
nonlocal original_to_copy
if getattr(node, attribute) in original_to_copy:
setattr(
node_copy, attribute, original_to_copy[getattr(node, attribute)]
)
else:
setattr(node_copy, attribute, Node(x=getattr(node, attribute).val))
original_to_copy[getattr(node, attribute)] = getattr(
node_copy, attribute
)

while node is not None:
if node.next is not None:
update_attribute(node, node_copy, "next")
if node.random is not None:
update_attribute(node, node_copy, "random")
node = node.next
node_copy = node_copy.next
return copy_head
44 changes: 44 additions & 0 deletions 0138.Copy-List-with-Random-Pointer/step2_wo_hashmap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
class Node:
def __init__(self, x: int, next: "Node" = None, random: "Node" = None):
self.val = int(x)
self.next = next
self.random = random


class Solution:
def copyRandomList(self, head: "Node" | None) -> "Node" | None:
if head is None:
return None

# original1->copy1->original2->copy2...
node = head
while node:
node_next = node.next
copy_node = Node(x=node.val)
node.next = copy_node
copy_node.next = node_next
node = node_next

# コピーしたノードのrandomを繋ぐ
node = head
while node:
if node.random:
node.next.random = node.random.next
node = node.next.next

# コピーを分離する
node = head
dummy_head = Node(0)
copy_node = dummy_head

while node:
node_next = node.next.next

copy_node_next = node.next
copy_node.next = copy_node_next
copy_node = copy_node_next

node.next = node_next
node = node_next

return dummy_head.next
44 changes: 44 additions & 0 deletions 0138.Copy-List-with-Random-Pointer/step3_wo_hashmap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from __future__ import annotations


class Node:
def __init__(self, x: int, next: Node = None, random: Node = None):
self.val = int(x)
self.next = next
self.random = random


class Solution:
def copyRandomList(self, head: Node | None) -> Node | None:
if head is None:
return None

node = head
while node:
node_next = node.next
copy_node = Node(x=node.val)
node.next = copy_node
copy_node.next = node_next
node = node_next

node = head
while node:
if node.random:
node.next.random = node.random.next
node = node.next.next

node = head
dummy_head = Node(0)
copy_node = dummy_head

while node:
node_next = node.next.next

copy_node_next = node.next
copy_node.next = copy_node_next
copy_node = copy_node_next

node.next = node_next
node = node_next

return dummy_head.next