日常系列LeetCode《14·链表1》

Posted 常某某的好奇心

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了日常系列LeetCode《14·链表1》相关的知识,希望对你有一定的参考价值。

数据规模->时间复杂度

<=10^4 😮(n^2)
<=10^7:o(nlogn)
<=10^8:o(n)
10^8<=:o(logn),o(1)

整体内容

lc 203 :移除链表元素
https://leetcode.cn/problems/remove-linked-list-elements/
提示:
列表中的节点数目在范围 [0, 104] 内
1 <= Node.val <= 50
0 <= val <= 50

#方案一:删除表头元素与非表头元素
# 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: Optional[ListNode], val: int) -> Optional[ListNode]:
        #删表头
        while head!=None and head.val==val:
            delnode=head #key
            head=head.next
            delnode.next=None

        #删表中
        if head==None:return None #key:head是指向第一个元素的,若此时为None,则没有next属性
        prev=head
        curr=head.next
        while curr:
            if curr.val==val:
                prev.next=curr.next
                curr.next=None
                curr=prev.next
            else:
                prev=curr
                curr=curr.next
        return head
        
#方案二:虚拟节点统一删除逻辑
# 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: Optional[ListNode], val: int) -> Optional[ListNode]:
        #建虚拟节点
        dummynode=ListNode(-1)
        dummynode.next=head
        #统一删除逻辑
        prev=dummynode
        curr=head
        while curr:
            if curr.val==val:
                prev.next=curr.next
                curr.next=None
                curr=prev.next
            else:
                prev=curr
                curr=curr.next
        return dummynode.next

lc 237 删除链表中的节点
https://leetcode.cn/problems/delete-node-in-a-linked-list/
提示:
链表中节点的数目范围是 [2, 1000]
-1000 <= Node.val <= 1000
链表中每个节点的值都是 唯一 的
需要删除的节点 node 是 链表中的节点 ,且 不是末尾节点

#方案一:
# 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.
        """
        while node:
            nextnode=node.next
            if nextnode:
                node.val=nextnode.val        
            else:
                prev.next=None
            #注:位置
            prev=node
            node=node.next       
             
#方案二:
# 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
        #
        nextN=node.next #注:标记
        node.next=nextN.next
        nextN.next=None #node.next.next=None会报错       

lc 83 :删除排序链表中的重复元素
https://leetcode.cn/problems/remove-duplicates-from-sorted-list/
提示:
链表中节点数目在范围 [0, 300] 内
-100 <= Node.val <= 100
题目数据保证链表已经按升序 排列

# 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: Optional[ListNode]) -> Optional[ListNode]:
        #
        if head==None or head.next==None:return head
        #
        prev=head
        curr=prev.next
        while curr:
            if curr.val==prev.val:
                prev.next=curr.next
                curr.next=None
                curr=prev.next
            else:
                prev=curr
                curr=prev.next
        return head

lc 82 :删除排序链表中的重复元素 II
https://leetcode.cn/problems/remove-duplicates-from-sorted-list-ii/
提示:
链表中节点数目在范围 [0, 300] 内
-100 <= Node.val <= 100
题目数据保证链表已经按升序 排列

# 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: Optional[ListNode]) -> Optional[ListNode]:
        if head==None or head.next==None:return head
        #
        dummynode=ListNode(-1)
        dummynode.next=head
        #
        prev=dummynode
        curr=head
        while curr:
            if curr.next and curr.next.val==curr.val:
                while curr.next and curr.next.val==curr.val:
                    curr=curr.next
                prev.next=curr.next
                curr.next=None
                curr=prev.next
            else:
                prev=curr
                curr=curr.next #curr=prev.next,可以和if里合并
        return dummynode.next

lc 876 :链表的中间结点
https://leetcode.cn/problems/middle-of-the-linked-list/
提示:
给定链表的结点数介于 1 和 100 之间。

#方案一:两遍扫描
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def middleNode(self, head: ListNode) -> ListNode:
        #链长
        length=0
        curr=head
        while curr:
            length+=1
            curr=curr.next
        #找
        for i in range(length//2):
            head=head.next
        return head
        
#方案二:快慢指针
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def middleNode(self, head: ListNode) -> ListNode:
        if head==None or head.next==None:return head
        slow=fast=head
        while fast and fast.next:#逆否命题
            slow=slow.next
            fast=fast.next.next
        return slow

19 【剑指 021】【top100】 :删除链表的倒数第 N 个结点
https://leetcode.cn/problems/remove-nth-node-from-end-of-list/
提示:
链表中结点的数目为 sz
1 <= sz <= 30
0 <= Node.val <= 100
1 <= n <= sz
进阶:
你能尝试使用一趟扫描实现吗?

#方案一:两遍扫描
# 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: Optional[ListNode], n: int) -> Optional[ListNode]:
        #
        dummynode=ListNode(-1)
        dummynode.next=head
        #链长
        length=0
        curr=dummynode
        while curr:
            length+=1
            curr=curr.next
        #找待删prev
        prev=dummynode
        for i in range(length-n-1):
            prev=prev.next
        #删
        delnode=prev.next
        prev.next=delnode.next
        delnode.next=None
        return dummynode.next

#方案二:快慢指针
# 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: Optional[ListNode], n: int) -> Optional[ListNode]:
        if not head:return head
        #
        dummynode=ListNode(-1)
        dummynode.next=head
        #fast先走n+1步
        slow=fast=dummynode
        for i in range(n+1):
            fast=fast.next
        # while n >= 0:
        #     fast = fast.next
        #     n -= 1
        while fast:
            slow=slow.next
            fast=fast.next
        #删:此时prev=slow
        delnode=slow.next
        slow.next=delnode.next
        delnode.next=None
        return dummynode.next

lc 141【top100】:环形链表
https://leetcode.cn/problems/linked-list-cycle/
提示:
链表中节点的数目范围是 [0, 104]
-105 <= Node.val <= 105
pos 为 -1 或者链表中的一个 有效索引 。
进阶:
你能用 O(1)(即,常量)内存解决此问题吗?

#方案一:hash查找
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def hasCycle(self, head: Optional[ListNode]) -> bool:
        #o(n),o(n)
        visited=set()
        curr=head
        while curr:
            if curr in visited:return True
            visited.add(curr)
            curr=curr.next
        return False
#方案二:快慢指针
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def hasCycle(self, head: Optional[ListNode]) -> bool:
        #o(n),o(1)
        slow=head
        fast=head
        while fast and fast.next:
            slow=slow.next
            fast=fast.next.next
            if slow==fast:return True
        return False

lc 142 【剑指 022 】【top100】:环形链表 II
https://leetcode.cn/problems/linked-list-cycle-ii/
提示:
链表中节点的数目范围在范围 [0, 104] 内
-105 <= Node.val <= 105
pos 的值为 -1 或者链表中的一个有效索引
进阶:
你是否可以使用 O(1) 空间解决此题?

#方案一:hash查找
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
    	#o(n),o(n)
        visited=set()
        curr=head
        while curr:
            if curr in visited:return curr
            visited.add(curr)
            curr=curr.next
        return None
        
#方案二:快慢指针
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
        #o(n).o(1)
        slow=fast=head
        while fast and fast.next:
            slow=slow.next
            fast=fast.next.next
            #有环
            if slow==fast:
                p=head
                while p!=slow:
                    p=p.next
                    slow=slow.next
                return p
        return None

lc 206【剑指 024】【top100】:反转链表
https://leetcode.cn/problems/reverse-linked-list/
提示:
链表中节点的数目范围是 [0, 5000]
-5000 <= Node.val <= 5000
进阶:
链表可以选用迭代或递归方式完成反转。你能否用两种方法解决这道题?

#方案一:迭代
# 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: Optional[ListNode]) -> Optional[ListNode]:
        prev=None
        curr=head
        while curr:
            nextN=curr.next
            curr.next=prev
            prev=curr
            curr=nextN
        return prev #key
        
#方案二:递归
# 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: Optional[ListNode]) -> Optional[ListNode]:
        #终条
        if not head or not head.next:return head
        #递
        p=self.reverseList(head.next)#子问题
        #归
        head.next.next=head
        head.next=None
        return p

lc 92 :反转链表 II
https://leetcode.cn/problems/reverse-linked-list-ii/
提示:
链表中节点数目为 n
1 <= n <= 500
-500 <= Node.val <= 500
1 <= left <= right <= n
进阶:
你可以使用一趟扫描完成反转吗?

#方案一:
# Definition for 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]:
        #
        dummynode=ListNode(-1)
        dummynode.next=head
        #四个位置
        #
        prev=dummynode
        for i in range(left-1):
            prev=prev.next
        leftN=prev.next
        #
        rightN=leftN
        for i in range(right-left):
            rightN=rightN.next
        post=rightN.next
        #先断
        prev.next=None
        rightN.next=None
        #部分反转
        self.reverseList(leftN)
        #后连
        prev.next=rightN
        leftN.next=post
        return dummynode.next

    def reverseList(self,node):
        prev=None
        curr=node
        while curr:
            nextN=curr.next
            curr.next=prev
            prev=curr
            curr=nextN

#方案二:头插法
# Definition for 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]:
        #
        dummynode=ListNode(-1)
        dummynode.next=head
        #
        prev=dummynode
        for i in range(left-1):
            prev=prev.next
        curr=prev.next
        #头插
        for i in range(right-left): #头插right-left次
            nextN=curr.next
            curr.next=nextN.next
            nextN.next=prev.next
            prev.next=nextN
        return dummynode.next        

lc 61 :旋转链表
https://leetcode.cn/problems/rotate-list/
提示:
链表中节点的数目在范围 [0, 500] 内
-100 <= Node.val <= 100
0 <= k <= 2 * 10^9

#方案一:链表反转法
# 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 or not head.next or k==0:return head    
        #
        length=0
        curr=head
        while curr:
            length+=1
            curr=curr.next
        #改进
        if k%length==0:return head
        k=k%length

        #反1
        newhead1=self.reverseList(head)
        #断
        kthnode=newhead1
        for i in range(k-1):
            kthnode=kthnode.next
        nexthead=kthnode.next
        kthnode.next=None
        #反2,反3,连
        reshead=self.reverseList(newhead1)
        newhead1.next=self.reverseList(nexthead)
        return reshead
        
    def reverseList(self,node):
        prev=None
        curr=node
        while curr:
            nextN=curr.next
            curr.next=prev
            prev=curr
            curr=nextN
        return prev
         
#方案二:处理关键节点
# 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 or not headleetCode第21题——合并两个有序链表

算法系列——合并K个升序链表

算法系列——合并K个升序链表

算法系列——合并K个升序链表

算法系列——合并K个升序链表

《LeetCode之每日一题》:98.删除排序链表中的重复元素