LeetCode 問題セット: リンク リスト (3)

この記事では、LeetCode問題集の連結リストの問題を紹介します。

リンクされたリストに関するその他の LeetCode の質問:
LeetCode 問題セット: リンクされたリスト (1)
LeetCode 問題セット: リンクされたリスト (2)


19. リストの最後から N 番目のノードを削除 (リンクされたリストの最後の N ノードを削除)


問題の説明

LeetCode 19 問題の説明

アイデアとコード


この問題には 2 つの解決策があります。

まず、最初にリストをトラバースして長さを決定し、次に別のトラバースを実行して、下から N 番目のノードを削除します。

コードは以下のように表示されます:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
        dummy = ListNode(val=-1, next=head)
        num_node = 0  # number of nodes
        while head:
            num_node += 1
            head = head.next

        res = dummy
        head = dummy
        while head.next:
            if num_node == n:
                head.next = head.next.next
                break
            else:
                num_node -= 1
                head = head.next

        res = res.next

        return res

実行結果:
LeetCode 19 ランニング効果 1

2つ目は、高速ポインタと低速ポインタの方法で、最初に高速ポインタをNステップ移動させてから、高速ポインタと低速ポインタを同時に移動させ、高速ポインタが最後まで移動すると、低速ポインタはN+1の一番下に移動します。ノードであり、その次のポイントが一番下の N-1 ノード (次の次のノード) を指していれば十分です。

コードは以下のように表示されます:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
        fast, slow = head, head
        
        # move fast n steps in advance
        for i in range(n):
            fast = fast.next

        # special case: remove the 1st node
        if not fast:
            return head.next

        # move fast and slow together
        while fast.next:
            fast = fast.next
            slow = slow.next
        slow.next = slow.next.next  # remove the nth node from the end

        return head

実行結果:
LeetCode 19 ランニングエフェクト 2


203. リンクされたリスト要素を削除する


問題の説明

LeetCode 203 問題の説明

アイデアとコード


この質問の考え方は単純で、ノードを 1 つずつトラバースし、削除する必要があるノードの前のノードの次のパラメーターを変更します。

コードは以下のように表示されます:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def removeElements(self, head: ListNode, val: int) -> ListNode:
        dummy = ListNode(val=-1, next=head)
        head = dummy
        while head.next:
            if head.next.val == val:
                head.next = head.next.next
            else:
                head = head.next

        res = dummy.next

        return res

実行結果:
LeetCode 203 ランニング効果


61. リストの回転


問題の説明

LeetCode 61 問題の説明 I
LeetCode 61 問題の説明 II

アイデアとコード


この質問の考え方は、連結リストの回転の結果を観察することです. 回転は、連結リストを 2 つのセグメントに切断してから再度結合することと同等であることがわかります. 切断位置は、回転数 k によって決定でき、対応するノードの次のパラメーターを変更できます。

2 つの特殊なケースに注意してください。

  • 連結リストが空の場合、元の空の連結リストに直接戻る
  • 連結リストの長さに対する回転数 k の余りを計算し、結果が 0 の場合は元の連結リストに戻る

コードは以下のように表示されます:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def rotateRight(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
        if not head:
            return head

        dummy = ListNode(val=-1, next=head)

        num_node = 0
        head = dummy
        while head.next:
            num_node += 1
            head = head.next

        # in case: k > num_node
        k %= num_node

        if not k:
            return dummy.next

        head_ori = dummy.next  # original head
        head = dummy.next
        for _ in range(num_node - k):
            head = head.next
        dummy.next = head  # new head
        for _ in range(k - 1):
            head = head.next
        head.next = head_ori  # next node of tail -> original head
        for _ in range(num_node - k):
            head = head.next
        head.next = None

        return dummy.next

実行結果:
LeetCode 61 ランニング効果 1

公式の問題解は別の考え方で、まず連結リストを環にし、回転数 k に応じて対応する節点の位置を求めて環を解くというものです。

LeetCode 61 公式ソリューション

コードは以下のように表示されます:

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def rotateRight(self, head: ListNode, k: int) -> ListNode:
        if not head or not head.next:
            return head
        
        n = 1  # number of nodes
        cur = head
        while cur.next:
            cur = cur.next
            n += 1
        
        k %= n  # k < n
        if not k:
            return head
        
        cur.next = head
        for _ in range(n - k):
            cur = cur.next
        
        res = cur.next
        cur.next = None  # break the loop

        return res

実行結果:
LeetCode 61 ランニング効果 2

おすすめ

転載: blog.csdn.net/Zhang_0702_China/article/details/121244241