Leetcode——链表

Leetcode——链表

  • 合并两个有序链表
  • 删除排序链表中的重复元素
  • 环形链表
  • 相交链表
  • 移除链表元素
  • 反转链表
  • 回文链表
  • 删除链表中的节点

链表(Linked List)是最简单的线性的、动态数据结构。理解它是理解树结构、图结构的基础。

区别于数组,链表中的元素不是存储在内存中连续的一片区域,链表中的数据存储在每一个称之为「结点」复合区域里,在每一个结点除了存储数据以外,还保存了到下一个节点的指针(Pointer)。
由于不必按顺序存储,链表在插入数据的时候可以达到 O(1)O(1) 的复杂度,但是查找一个节点或者访问特定编号的节点则需要 O(n)O(n) 的时间。
链表示意图

使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。

在计算机科学中,链表作为一种基础的数据结构可以用来生成其它类型的数据结构。链表通常由一连串节点组成,每个节点包含任意的实例数据(data fields)和一或两个用来指向上一个/或下一个节点的位置的链接(links)。链表最明显的好处就是,常规数组排列关联项目的方式可能不同于这些数据项目在记忆体或磁盘上顺序,数据的访问往往要在不同的排列顺序中转换。而链表是一种自我指示数据类型,因为它包含指向另一个相同类型的数据的指针(链接)。

链表允许插入和移除表上任意位置上的节点,但是不允许随机存取。链表有很多种不同的类型:单向链表,双向链表以及循环链表。

链表通常可以衍生出循环链表,静态链表,双链表等。对于链表使用,灵活使用虚拟头结点可以简化问题。

合并两个有序链表

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 Leetcode——链表_第1张图片

输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]

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

class Solution:
    def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:

        prehead = ListNode(-1)
        new_list = prehead
        while l1 and l2:
            if l1.val <= l2.val:
                new_list.next = l1
                l1 = l1.next
            else:
                new_list.next = l2
                l2 = l2.next
            new_list = new_list.next
        
        new_list.next = l1 if l1 is not None else l2

        return prehead.next

删除排序链表中的重复元素

存在一个按升序排列的链表,给你这个链表的头节点 head ,请你删除所有重复的元素,使每个元素 只出现一次 。返回同样按升序排列的结果链表。

Leetcode——链表_第2张图片

输入:head = [1,1,2]
输出:[1,2]

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def deleteDuplicates(self, head: ListNode) -> ListNode:

        if not head:
            return head
        
        curr = head        
        while curr.next:
            if curr.val == curr.next.val:
                curr.next = curr.next.next
                # curr = None
            else:
                curr = curr.next          
        
        return head

环形链表

给定一个链表,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

如果链表中存在环,则返回 true 。 否则,返回 false 。
Leetcode——链表_第3张图片

输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def hasCycle(self, head: ListNode) -> bool:

        if not head:
            return False

        cur = head
        res = set()
        while cur:
            node = cur
            # print(node.val)
            if node in res:
                return True
            res.add(node)
            cur = cur.next
        return False

相交链表

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。

图示两个链表在节点 c1 开始相交:
Leetcode——链表_第4张图片
题目数据 保证 整个链式结构中不存在环。

注意,函数返回结果后,链表必须 保持其原始结构 。

示例 1:
Leetcode——链表_第5张图片

输入: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 个节点。

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:

        if not headA:
            return null
        if not headB:
            return null

        currA, currB = headA, headB
        a, b = 0, 0

        while currA:
            a += 1
            currA = currA.next
        
        while currB:
            b += 1
            currB = currB.next
        
        if a>b:
            currL = headA
            diff = a-b
            currS = headB
        else:
            currL = headB
            diff = b-a
            currS = headA
        
        i = 0
        while i < diff:
            i += 1
            currL = currL.next
        
        while currL != currS:
            currS = currS.next
            currL = currL.next
        
        return currL

移除链表元素

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。
Leetcode——链表_第6张图片

输入:head = [1,2,6,3,4,5,6], val = 6
输出:[1,2,3,4,5]

# 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:
        p = ListNode(-1)
        p.next = head
        llist = p

        while llist.next:
            if llist.next.val == val:
                llist.next = llist.next.next
            else:
                llist = llist.next
        return p.next

反转链表

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
Leetcode——链表_第7张图片

输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        prev, curr = None, head

        while curr:
            # nxt = 2-3-4-5
            nxt = curr.next
            # 1 -> None
            curr.next = prev
            # prev -> 1
            prev = curr
            # curr = nxt = 2-3-4-5
            curr = nxt
        return prev

回文链表

给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。

在这里插入图片描述

输入:head = [1,2,2,1]
输出:true

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def isPalindrome(self, head: ListNode) -> bool:
        
        res = []
        curr = head

        while curr is not None:
            # print(curr.val)
            res.append(curr.val)
            curr = curr.next
        
        return res == res[::-1]

删除链表中的节点

请编写一个函数,使其可以删除某个链表中给定的(非末尾)节点。传入函数的唯一参数为 要被删除的节点。
现有一个链表 – head = [4,5,1,9],它可以表示为:

在这里插入图片描述

输入:head = [4,5,1,9], node = 5
输出:[4,1,9]
解释:给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9.

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def deleteNode(self, node):
        """
        :type node: ListNode
        :rtype: void Do not return anything, modify node in-place instead.
        """
        node.val = node.next.val
        node.next = node.next.next

你可能感兴趣的:(Leetcode——刷题,链表,leetcode,数据结构)