leetcode分类刷题:链表(一、创建虚拟头节点)

1、现在再看链表问题,发现之前对傻傻分不清的cur.next有了更清晰的理解了:以cur变量表示当前节点,cur.next当前节点的指针下个节点,以上两个含义是一个意思,但在实际代码里选择其中一个进行理解会在逻辑上更清晰
2、cur.next != None出现在if或while的条件位置时,按照下个节点理解
3、cur.next = xxxxx,即cur.next放在等号左侧时,按照给当前节点的指针赋值理解
4、xxxxx = cur.next,即cur.next放在等号右侧时,按照指向或操作下个节点理解
5、本文针对的总结题型为建立虚拟头节点解决的问题,这类问题在进行对头节点的操作时,与其它节点会不一致,因此建立虚拟头节点使得所有节点的操作一致,最后返回dummyHead.next

203. 移除链表元素

链表的基本操作,删除当前节点,需要获取上个节点,因此cur指向当前节点,对下个节点cur.next进行访问和操作,此时,提前创建虚拟头节点 方便删除头节点时不用额外判断

from typing import Optional
'''
203. 移除链表元素
题目描述:给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点.
示例 1:
    输入:head = [1,2,6,3,4,5,6], val = 6
    输出:[1,2,3,4,5]
题眼:无。
思路:删除当前节点,需要获取上个节点,因此cur指向当前节点,对下个节点cur.next进行访问和操作,此时,提前创建虚拟头节点 方便删除头节点时不用额外判断
'''


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


class Solution:
    def removeElement(self, head: Optional[ListNode], val: int) -> Optional[ListNode]:
        # 情况1、链表为空
        if head == None:
            return None
        # 情况2、链表非空
        # 思路、删除当前节点,需要获取上个节点,因此cur指向当前节点,对下个节点cur.next进行访问和操作
        dummyHead = ListNode()  # 虚拟头节点:方便删除头节点时不用额外判断
        dummyHead.next = head
        cur = dummyHead
        # 接下来的操作节点为cur.next,即当前节点的下个节点
        while cur.next != None:
            # 只有cur.next不为None时,才有属性val和next
            if cur.next.val == val:
                cur.next = cur.next.next  # 删除操作
            else:  # 注意非删除操作时,才会更新cur,否则会刚好跳过刚删除节点后的节点的判断
                cur = cur.next
        head = dummyHead.next
        return head


if __name__ == "__main__":
    obj = Solution()
    while True:
        try:
            in_line = input().strip().split('=')
            nums = []
            if in_line[1].split('[')[1].split(']')[0] != '':
                nums = [int(n) for n in in_line[1].split('[')[1].split(']')[0].split(',')]
            val = int(in_line[2])
            print(nums, val)
            # 创建链表
            dummyHead = ListNode()  # 定义一个虚拟头节点
            cur = dummyHead  # cur用来遍历建立链表
            for n in nums:
                cur.next = ListNode(n)
                cur = cur.next
            head = dummyHead.next
            result = obj.removeElement(head, val)
            # 输出链表
            ans = []
            cur = result
            while cur != None:
                ans.append(cur.val)
                cur = cur.next
            print(ans)
        except EOFError:
            break

24. 两两交换链表中的节点

两两交换 <=> 删除后一个节点+再插入后一个节点到前一个节点之前

from typing import Optional
'''
24. 两两交换链表中的节点
题目描述:给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。
        你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
示例 1:
    输入:head = [1,2,3,4]
    输出:[2,1,4,3]
题眼:两两交换节点 + 不修改节点内部的值
思路:两两交换 <=> 删除后一个节点+再插入后一个节点到前一个节点之前
'''


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


class Solution:
    def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
        # 情况1、链表为空或链表节点数为1,没有任何操作
        if head == None or head.next == None:
            return head
        # 情况2、链表节点数大于等于2
        dummyHead = ListNode()  # 创建虚拟头节点,使得对头节点的操作与其它节点一致
        dummyHead.next = head
        cur = dummyHead
        while cur.next != None and cur.next.next != None:  # 参与交换的两个节点均不为空
            # 1、删除后一个节点
            temp = cur.next.next  # 标记后一个节点
            cur.next.next = cur.next.next.next
            # 2、再插入后一个节点到前一个节点之前
            temp.next = cur.next
            cur.next = temp
            # 更新循环条件
            cur = cur.next.next
        return dummyHead.next


if __name__ == "__main__":
    obj = Solution()
    while True:
        try:
            in_line = input().strip().split('[')[-1].split(']')[0]
            if in_line == '':
                head = None
                print([])
            else:
                nums = [int(n) for n in in_line.split(',')]
                head = ListNode(nums[0], None)  # 创建头节点
                cur = head
                for i in nums[1:]:  # 添加链表元素
                    newNode = ListNode(i, None)
                    cur.next = newNode
                    cur = cur.next
                # 输出原始链表
                cur = head
                while cur != None:
                    print(cur.val, end=' ')
                    cur = cur.next
                print()
                # 调用函数
                result = obj.swapPairs(head)
                # 输出结果链表
                cur = result
                while cur != None:
                    print(cur.val, end=' ')
                    cur = cur.next
                print()
        except EOFError:
            break

92. 反转链表 II

1、一次遍历,对[left, right]内的节点执行“206. 反转链表”操作,并对left节点及前一个节点标记
2、这道题不像上两个题让cur等于dummyHead进行遍历,以使得对所有节点的操作一致,而是设置pre等于dummyHead,算是达到了等价的效果,不然无法在对head有操作时最后返回dummyHead.next作为答案

from typing import Optional
'''
92. 反转链表 II
题目描述:给你单链表的头指针 head 和两个整数left 和 right ,其中left <= right 。
请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。
示例 1:
    输入:head = [1,2,3,4,5], left = 2, right = 4
    输出:[1,4,3,2,5]
题眼:反转链表
思路:一次遍历,对[left, right]内的节点执行“206. 反转链表”操作,并对left节点及前一个节点标记
'''


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


class Solution:
    def reverseBetween(self, head: Optional[ListNode], left: int, right: int) -> Optional[ListNode]:
        # 注意链表的节点数从1开始算起
        dummyHead = ListNode()
        dummyHead.next = head  # 创建虚拟头节点,方便left=1即为头节点时 的操作 与其它节点一致
        pre, cur = dummyHead, head  # 类似“206. 反转链表”赋值pre为None
        leftPre, leftCur = None, None  # 对left节点及前一个节点标记
        for i in range(1, right + 1):
            if i >= left:
                if i == left:
                    leftPre, leftCur = pre, cur  # 记录left前一个节点和left节点
                post = cur.next
                cur.next = pre
                pre, cur = cur, post
            else:
                pre, cur = cur, cur.next
        leftPre.next = pre  # 此时pre指向第right个节点
        leftCur.next = cur  # 此时cur指向right后一个节点
        return dummyHead.next


if __name__ == "__main__":
    while True:
        try:
            in_line = input().strip().split('=')
            nums = [int(n) for n in in_line[1].split('[')[1].split(']')[0].split(',')]
            left = int(in_line[2].split(',')[0])
            right = int(in_line[3])
            # print(nums, left, right)
            # 创建链表
            dummyHead = ListNode()
            cur = dummyHead
            for n in nums:
                cur.next = ListNode(n, None)
                cur = cur.next
            head = dummyHead.next
            # 打印链表
            result = head
            ans = []
            cur = result
            while cur != None:
                ans.append(cur.val)
                cur = cur.next
            print(ans)
        except EOFError:
            break

你可能感兴趣的:(数据结构与算法,leetcode)