leetcode 分類テストの質問: リンク リスト (2、ダブル ポインター)

1. リンク リストの問題をもう一度見てみると、以前は混乱していたcur.nextがより明確に理解できるようになりました。 cur 変数は現在のノードを表し、 cur.nextは現在のノードまたはのノードのポインタです。 node、上記の 2 つ 意味は同じですが、実際のコードで理解するにはどちらかを選択した方が論理的に明確になります。
2. cur.next != if または while の条件位置に何も表示されないので次のように理解してください。次のノード
3. cur.next = xxxxx、つまり cur.next が等号の左側にある場合、現在のノードのポインタ割り当てられます
4. xxxxx = cur.next、つまり,等号の右側に cur.next を置くと、次のノードを指す、または操作します理解
5. この記事で対象とする要約質問タイプは、ダブルポインタを使用して解決されます。

206. 逆リンクリスト

ダブルポインタのフロントポインタとバックポインタは、バックポインタがフロントポインタを指すように変更しますが、ポイントはバックポインタのポイントをあらかじめ格納しておき、Noneを特別なノードとして扱うことです

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next


class Solution:
    def reversedList(self, head: ListNode) -> ListNode:
        # 情况1、链表为空
        if head == None:
            return None
        # 情况2、链表非空
        pre, cur = None, head  # 没想到这样给初始值
        while cur != None:
            post = cur.next  # 存储下个节点
            cur.next = pre  # 反转
            pre, cur = cur, post  # 更新两个指针
        return pre


if __name__ == "__main__":
    obj = Solution()
    while True:
        try:
            in_line = input().strip().split('[')[-1].split(']')[0]
            nums = []
            head = None
            if in_line == '':
                print([])
            else:
                nums = [int(n) for n in in_line.split(',')]
                head = ListNode(nums[0], None)  # 创建链表头节点
                cur = head
                for n in nums[1:]:  # 添加链表元素
                    cur.next = ListNode(n, None)
                    cur = cur.next
                # 打印链表: 不用虚拟头节点也可以很方便地进行遍历打印
                cur = head
                while cur != None:
                    print(cur.val, end=' ')
                    cur = cur.next
            obj.reversedList(head)
        except EOFError:
            break

19. リンクリストの下から N 番目のノードを削除します。

ダブル ポインターの高速ポインターと低速ポインターの場合、リンク リストに合計 m 個のノードがあると仮定すると、最後から n 番目のノードは m-n+1 番目のノードに相当します。リンク リストのノード インデックスに注意してください。質問の意味に応じて 1 から始まります

from typing import Optional
'''
19. 删除链表的倒数第 N 个结点
题目描述:给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
示例 1:
    输入:head = [1,2,3,4,5], n = 2
    输出:[1,2,3,5]
题眼:假设链表一共m个节点,倒数第n个节点 等价于 第m-n+1个节点
注意:链表的节点索引从1开始
思路:
'''


class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next


class Solution:
    def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
        # 注意链表的节点索引从1开始
        # 假设链表一共m个节点,倒数第n个节点 等价于 第m-n+1个节点
        # 删除第m-n+1个节点 需要找到 第m-n个节点
        dummyHead = ListNode()  # 创建虚拟头节点,使得对头节点的操作与其它节点一致
        dummyHead.next = head
        slow, fast = 0, 0  # 双指针之快慢指针,索引用来标记是第几个节点,减少代码错误
        slowCur, fastCur = dummyHead, dummyHead
        while fastCur != None:
            if fast > n:  # 当快指针移动到第n个节点时,慢指针同步移动,最终遍历完链表时,慢指针刚好移动m-n步,指向 第m-n个节点
                slow += 1
                slowCur = slowCur.next
            fast += 1
            fastCur = fastCur.next
        slowCur.next = slowCur.next.next
        return dummyHead.next


if __name__ == "__main__":
    obj = Solution()
    while True:
        try:
            in_line = input().strip().split('=')
            nums = [int(n) for n in in_line[1].split('[')[1].split(']')[0].split(',')]
            n = int(in_line[2].strip())
            head = ListNode(nums[0])
            cur = head
            for i in range(1, len(nums)):
                cur.next = ListNode(nums[i])
                cur = cur.next
            obj.removeNthFromEnd(head, n)
        except EOFError:
            break

160. 交差リンクリスト

アイデア 1:ハッシュ テーブルを使用した非常に単純な質問アイデア
2:ダブル ポインタの高速ポインタと低速ポインタ: 各ポインタは異なるリンク リストから始まり、現在のリンク リストをたどった後、別のリンク リストの先頭に変わります交差点がある場合、2 つのステップは、数字がまったく同じであれば交差点に到達しますが、そうでない場合は、2 番目のリンク リストの最後に到達します。

'''
160. 相交链表
题目描述:给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。
示例 1:
    输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
    输出:Intersected at '8'
    解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。
    从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。
    在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。
题眼:链表相交
思路1:用哈希表很简单的一个题
思路2:双指针:每个指针分别从不同链表出发,走完当前链表就换另一个链表开头继续走,如果有交点,两者步数刚好一致走到交点;否则刚好都走到第二个链表的末尾
'''
from typing import Optional


class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next


class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        # 思路1、用哈希表很简单的一个题
        # hashTable = set()
        # cur = headA
        # while cur != None:
        #     hashTable.add(cur)
        #     cur = cur.next
        # cur = headB
        # while cur != None:
        #     if cur in hashTable:
        #         return cur
        #     cur = cur.next
        # return None

        # 思路2、根据快慢法则,走的快的一定会追上走得慢的
        # 在这道题里,有的链表短,他走完了就去走另一条链表,我们可以理解为走的快的指针。
        # 那么,只要其中一个链表走完了,就去走另一条链表的路。如果有交点,他们最终一定会在同一个位置相遇
        curA, curB = headA, headB
        while curA != curB:
            if curA != None:
                curA = curA.next
            else:
                curA = headB  # 如果headA走完了,那么就切换到headB走

            if curB != None:
                curB = curB.next
            else:
                curB = headA  # 同理,headB走完了就切换到headA
        return curA

142. 循環リンクリスト II

アイデア 1.ハッシュ テーブルの使用は非常に簡単です
アイデア 2.ダブル ポインタの高速ポインタと低速ポインタ: 最初のステップはリングがあるかどうかを確認することであり、2 番目のステップはリングのエントリ ノードを見つけることです。

'''
142. 环形链表 II
题目描述:给定一个链表的头节点  head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
示例 1:
    输入:head = [3,2,0,-4], pos = 1
    输出:返回索引为 1 的链表节点
    解释:链表中有一个环,其尾部连接到第二个节点。
题眼:环形链表+入环的第一个节点
思路1、用哈希表很简单
思路2、第一步检查是否有环,第二步定位环的入口节点
    1、快慢指针检查环是否存在,快指针一次走2步,慢指针一次走1步,相对慢指针而言,快指针在一次一步的靠近慢指针,相遇代表存在环
    2、入口涉及到数学推导获得结论,有点难
'''


# define singly-linked list
class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next


class Solution:
    def detectCycle(self, head: ListNode) -> ListNode:
        # 情况1、链表为空
        if head == None:
            return None
        # 思路1、用哈希表很简单
        # hashTable = set()
        # cur = head
        # while cur != None:
        #     if cur not in hashTable:
        #         hashTable.add(cur)
        #     else:  # 出现重复节点说明有环;且第一次出现的节点为起始节点
        #         return cur
        #     cur = cur.next
        # return None

        # 思路2、
        slow, fast = head, head
        while fast != None and fast.next != None:  # 这个判断条件容易写成fast.next.next!=None,这是错的,这里没有虚拟头节点了
            fast = fast.next.next
            slow = slow.next
            if fast == slow:  # 快慢指针相遇,说明有环
                start = head  # 寻找环的开头,根据结论:x=z
                while start != slow:
                    start = start.next
                    slow = slow.next
                return start  # 返回环的入口
        return None


if __name__ == "__main__":
    while True:
        try:
            in_line = input().strip().split(']')
            nums = [int(n) for n in in_line[0].split('[')[1].split(',')]
            pos = int(in_line[1].split('=')[1].strip())
            # 创建头节点
            head = ListNode(nums[0], None)
            cur = head
            if pos == 0:
                ring = head
            for i in range(1, len(nums)):
                cur.next = ListNode(nums[i], None)  # 添加第i个节点
                if pos == i:
                    ring = cur.next
                cur = cur.next
            if pos != -1:
                cur.next = ring
            # 输出原始链表
            cur = head
            n = 0
            while cur != None:
                print(cur.val, end=' ')
                cur = cur.next
                n += 1
                if n > 20:
                    break
            print()
            # 调用函数
            obj = Solution()
            result = obj.detectCycle(head)
            if result != None:
                print(result.val)
            else:
                print(result)
        except EOFError:
            break

おすすめ

転載: blog.csdn.net/qq_39975984/article/details/132529559
おすすめ