LeetCode 题目 138: ランダム ポインターを含む重複リンク リスト (Python コード)

トピック138. ランダム ポインターを使用したリンク リストのコピーについては、次のように説明します。長さnnのリストが与えられた場合nのリンク リストでは、各ノードは通常のノードよりも追加のランダム ポインタを持ちramdom、ポインタはリンク リスト内の任意のノードまたは空のノードを指すことができます。このリンクされたリストのディープ コピーを作成しますいわゆるディープ コピーは、異なるメモリ アドレスを持つ新しいオブジェクトを完全に生成するため、コピー前に変数を変更しても、コピーされた変数には影響しません。

ハッシュマップ1

最初に、ユーザー skyliuhc からのより独創的なソリューションを投稿します。公式ソリューションの下のコメントでわかります。彼は Java バージョンを書きました。ここでは私が Python バージョンを書きます。

主なアイデアは、ループを使用して古いリンク リストと新しいリンク リストに対応する 2 つのノードを 2 つのタプルにバンドルし、ループを使用して新しいリンク リストの各ノードへのnext割り当てrandomを完了することです。

class Solution:
    def copyRandomList(self, head: 'Optional[Node]') -> 'Optional[Node]':
        if not head: return None
        cur = head
        hashmap = {
    
    }  # 哈希表
        # 第一个循环,建立映射
        while cur:
            hashmap[cur] = Node(cur.val)  # 新旧链表对应结点映射
            cur = cur.next  # 当前结点往后移动
        # 第二个循环,next 和 random 赋值
        cur = head
        while cur:
            # 因为 Python 的字典中不能用 None 作为键值,所以要做一个特殊判断
            hashmap[cur].next = hashmap[cur.next] if cur.next else None
            hashmap[cur].random = hashmap[cur.random] if cur.random else None
            cur = cur.next
        return hashmap[head]

ハッシュマップ2

これは、質問をしているときに考えた方法です。前のアイデアと似ています。また、ハッシュ テーブルを使用して、新旧のリンク リストのノードを記録するつもりですが、アイデアはより複雑です。具体的なアイデアは次のとおりです。

  • 1. まず、最も一般的なリンク リストを作成し、2 つを記録しますHashmap
    • 1.1、 :Node2Pos古いリンクリスト内のそれぞれNodeの位置
    • 1.2、Pos2Node: 新しいリンクされたリストの各位置は、Node
  • 2. 古いリンク リストと新しいリンク リストを同期的に走査して、現在の位置にある古いノードのランダム ノードに対応する位置を取得しますpos
  • 3.pos位置を通じて新しいリンク リストのノードを取得し、現在のノードのランダムがどこを指しているかを知ります。
class Solution:
    def copyRandomList(self, head: 'Optional[Node]') -> 'Optional[Node]':
        if not head: return None
        Node2Pos = {
    
    }  # 旧链表的每个 `Node` 的位置
        Pos2Node = {
    
    }  # 新链表每个位置对应的 `Node`
        # 构建新链表
        newPreHead = Node(0)  # 前置结点
        new_ptr = newPreHead  # 新链表的头结点
        old_ptr = head  # 旧链表的头结点 
        idx = 0 # 当前的位置
        while old_ptr: 
            Node2Pos[old_ptr] = idx  # 记录旧结点位置
            new_ptr.next = Node(old_ptr.val)
            new_ptr = new_ptr.next
            Pos2Node[idx] = new_ptr  # 记录当前位置的新结点
            idx += 1  # 位置也要同步往后
            old_ptr = old_ptr.next
        Pos2Node[idx] = None  # 最后一个位置是空指针 None
        
        # 处理 random node
        new_ptr = newPreHead.next
        old_ptr = head
        while old_ptr:
            random_node = old_ptr.random  # 获得旧结点的随机结点
            # 获得旧结点随机结点的位置,如果为随机结点为空代表是最后一个位置,即 idx
            pos = Node2Pos[random_node] if random_node else idx
            node = Pos2Node[pos]  # 获得对应 pos 的结点
            new_ptr.random = node
            new_ptr = new_ptr.next
            old_ptr = old_ptr.next
        
        return newPreHead.next  # 返回结果

バックトラッキング + ハッシュテーブル

公式解決策: バックトラッキング方式を使用して、各ノードのコピー操作を互いに独立させます。現在のノードについては、最初にコピーし、次に「現在のノードの後継ノード」と「ランダム ポインタが指すノード」をコピーします。コピーが完了します。次に、作成した新しいノードのポインタを返し、現在のノードの 2 つのポインタの割り当てを完了します。

具体的な方法は次のとおりです。

  • まずハッシュ テーブルを作成しcachedNode、ヘッド ノードからトラバースします。
  • ノードが空の場合は、 を返しますNone
  • val現在通過しているノード値と同じ値を持つ新しいノードを作成します。
  • 次に、トラバースして値をnextとに割り当てますrandom
class Solution:
    def __init__(self,):
        self.cachedNode = {
    
    }
    
    def copyRandomList(self, head: 'Optional[Node]') -> 'Optional[Node]':
        if not head: return None
        if head not in self.cachedNode.keys():
            headNew = Node(head.val)  # 拷贝新节点
            self.cachedNode[head] = headNew  # 记录到哈希表中
            headNew.next = self.copyRandomList(head.next)
            headNew.random = self.copyRandomList(head.random)
        return self.cachedNode[head]

反復 + ノード分割

  • リンクされたリストの場合はA => B => C、 に変更できますA => A' => B => B' => C => C'。ここで、はA'Aコピー ノードです。
class Solution:
    def copyRandomList(self, head: 'Optional[Node]') -> 'Optional[Node]':
        if not head: return None
        # 将 A => B 变成 A => A' => B => B'
        node = head
        while node:
            nodeNew = Node(node.val)
            nodeNew.next = node.next
            node.next = nodeNew
            node = node.next.next
        
        # 处理 random
        node = head
        while node:
            nodeNew = node.next
            nodeNew.random = node.random.next if node.random else None
            node = node.next.next
            
        # 将 A => A' => B => B' 变成 A => B
        headNew = head.next
        node = head
        while node:
            nodeNew = node.next
            node.next = node.next.next
            nodeNew.next = nodeNew.next.next if nodeNew.next else None
            node = node.next
        
        return headNew

おすすめ

転載: blog.csdn.net/weixin_39679367/article/details/124477612