zoukankan      html  css  js  c++  java
  • 【Leetcode】链表系列

    【Leetcode-3】

    一、题目:两数相加

      给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。

      请你将两个数相加,并以相同形式返回一个表示和的链表。

      你可以假设除了数字 0 之外,这两个数都不会以 0 开头。

    二、代码:

    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, val=0, next=None):
    #         self.val = val
    #         self.next = next
    class Solution:
        def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
            last_v = 0
            p1, p2 = l1, l2
            head = p = ListNode(0)
            while p1 or p2 or last_v:
                v1 = p1.val if p1 else 0
                v2 = p2.val if p2 else 0
                v = v1 + v2 + last_v
                node = ListNode(v%10)
                last_v = v // 10
                p.next = node
                p = p.next
                if p1:
                    p1 = p1.next
                if p2:
                    p2 = p2.next
            return head.next

    【Leetcode-19】

    一、题目:删除链表的倒数第n个结点

      给你一个链表,删除链表的倒数第 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:
            if not head:
                return head
            p = ListNode(0)
            p.next = head
            p1 = p2 = p
            for i in range(n):
                p2 = p2.next
            while p2 and p2.next:
                p1 = p1.next
                p2 = p2.next
                
            p1.next = p1.next.next
            return p.next

    【Leetcode-21】

    一、题目:合并两个有序链表

      将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

    二、代码:

    # 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:
            head = p = ListNode()
            p1, p2 = l1, l2
            while p1 or p2:
                v1 = p1.val if p1 else float('inf')
                v2 = p2.val if p2 else float('inf')
                if v1 < v2:
                    p.next = p1
                    p1 = p1.next
                else:
                    p.next = p2
                    p2 = p2.next
                p = p.next
            return head.next

    【Leetcode-23】

    一、题目:合并k个升序链表

      给你一个链表数组,每个链表都已经按升序排列。

      请你将所有链表合并到一个升序链表中,返回合并后的链表。

    二、代码:

    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, val=0, next=None):
    #         self.val = val
    #         self.next = next
    class Solution:
        def mergeKLists(self, lists: List[ListNode]) -> ListNode:
            """
            分治思想,类似于归并排序
            """
            def split_and_merge(lists, l, r):
                if l == r:
                    return lists[l]
                mid = (l + r) // 2
                l1 = split_and_merge(lists, l, mid)
                l2 = split_and_merge(lists, mid+1, r)
                lt = merge_list(l1, l2)
                return lt
    
            def merge_list(l1, l2):
                dummy = ListNode()
                p1, p2, p = l1, l2, dummy
                while p1 or p2:
                    val1 = p1.val if p1 else float('inf')
                    val2 = p2.val if p2 else float('inf')
                    if val1 < val2:
                        p.next = p1
                        p1 = p1.next
                    else:
                        p.next = p2
                        p2 = p2.next
                    p = p.next
                return dummy.next
    
            if not lists:
                return
            n = len(lists)
            l = split_and_merge(lists, 0, n-1)
            return l

    【Leetcode-24】

    一、题目:两两交换链表中的结点

      给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。

      你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

    二、代码:

    class Solution:
        def swapPairs(self, head: ListNode) -> ListNode:
            """
            每次走两步,交换2节点,若步数不到2则不交换
            """
            dummy = ListNode()
            dummy.next = head  # 哑节点,避免处理头
            p = dummy  # p指向处理完成的节点
            # 0-1-2-3..,p开始指向0
            while p.next and p.next.next:  
                tmp = p.next.next  # tmp=2
                p.next.next = tmp.next  # 1-3
                tmp.next = p.next  # 2-1
                p.next = tmp  # 0-2
                p = p.next.next
            return dummy.next

    【Leetcode-25】

    一、题目:K个一组翻转链表

      给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。

      k 是一个正整数,它的值小于或等于链表的长度。

      如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。

    二、代码:

    def reverseKGroup(self, head: ListNode, k: int) -> ListNode:
            """
            pre指向拼接完成链表的尾部,head和tail分别指向待翻转部分的头部和尾部,nxt指向未翻转部分的头部,如果没走k步就到了None,那么直接break
            """
            def reverse(head):
                final_tail = head
                pre = None
                p = head
                while p:
                    tmp = p.next
                    p.next = pre
                    pre = p
                    p = tmp
                return pre, final_tail
    
            dummy = ListNode(0, head)
            pre, tail, head = dummy, dummy, dummy.next
            while pre:  # 未翻转完
                i = 0
                while i < k:
                    tail = tail.next
                    if not tail:
                        return dummy.next
                    i += 1
                # 断开再翻转
                nxt = tail.next
                tail.next = None
                head, tail = reverse(head)
                # 接起来
                pre.next = head
                tail.next = nxt
                pre = tail
                head = tail.next
            return dummy.next

    【Leetcode-61】

    一、题目:旋转链表

      给你一个链表的头节点 head ,旋转链表,将链表每个节点向右移动 k 个位置。

    二、代码:

    def rotateRight(self, head: ListNode, k: int) -> ListNode:
            """
            链表长度n,移动k%n次
            移动方法:把链表连成环,起始在head,然后在后移n-k-1处切开
            1->2->3->4->5,k=1则移动5-1-1=3次,到4,4处切开,返回5处
            """
            if not head or not head.next or k == 0:
                return head
            # 计算链表长度
            n = 1
            p = head
            while p.next:
                n += 1
                p = p.next
            if n <= 1 or k % n == 0:  # 不必移动
                return head
            k = k % n
            # 连成环
            p.next = head
            p = head
            k = n - k - 1  # 在此后面断开
            while k > 0:  # 
                k -= 1
                p = p.next
            # 切开
            h = p.next
            p.next = None
            return h

    【Leetcode-82】

    一、题目:删除排序链表中的重复元素2

      存在一个按升序排列的链表,给你这个链表的头节点 head ,请你删除链表中所有存在数字重复情况的节点,只保留原始链表中 没有重复出现 的数字。

      返回同样按升序排列的结果链表。

    二、代码:

    def deleteDuplicates(self, head: ListNode) -> ListNode:
            """
            pre指向已处理完的链表,判断pre.next是否是重复的,重复就循环删除
            注意:
            1.不重复直接往下走
            2.重复的话pre不往下走,因为此刻只是走到了一个重复元素的下一个,这个元素不知道会不会重复,也是未处理,因此pre不变
            """
            dummy = ListNode(0, head)
            pre = dummy
            while pre:  # 未处理完
                if pre.next and pre.next.next and pre.next.val == pre.next.next.val:
                    # 已经重复,删除这个元素,一直过了这个元素到下一位
                    p = pre.next
                    val = p.val
                    while p and p.val == val:
                        p = p.next
                    pre.next = p
                else:
                    pre = pre.next
            return dummy.next

    【Leetcode-86】

    一、题目:分割链表

      给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。

      你应当 保留 两个分区中每个节点的初始相对位置。

    二、代码:

    def partition(self, head: ListNode, x: int) -> ListNode:
            """
            慢指针p1指向<x的元素的尾部,快指针p2指向待处理的元素,遇到<x的元素则接到p1的后面,pre指向p2的前一个用于接链表
            """
            dummy = ListNode(0, head)
            p1, pre, p2 = dummy, dummy, head
            while p2:
                if p2.val < x:
                    # 拆出来再插入
                    pre.next = p2.next
                    p2.next = p1.next
                    p1.next = p2
                    p1 = p1.next
                pre = p2
                p2 = p2.next
            return dummy.next

    【Leetcode-138】

    一、题目:复制带随机指针的链表

      给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 random ,该指针可以指向链表中的任何节点或空节点。

      构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成,其中每个新节点的值都设为其对应的原节点的值。新节点的 next 指针和 random 指针也都应指向复制链表中的新节点,并使原链表和复制链表中的这些指针能够表示相同的链表状态。复制链表中的指针都不应指向原链表中的节点 。

      例如,如果原链表中有 X 和 Y 两个节点,其中 X.random --> Y 。那么在复制链表中对应的两个节点 x 和 y ,同样有 x.random --> y 。

      返回复制链表的头节点。

      用一个由 n 个节点组成的链表来表示输入/输出中的链表。每个节点用一个 [val, random_index] 表示:

      val:一个表示 Node.val 的整数。
      random_index:随机指针指向的节点索引(范围从 0 到 n-1);如果不指向任何节点,则为  null 。
      你的代码 只 接受原链表的头节点 head 作为传入参数。

    二、代码:

    """
    # Definition for a Node.
    class Node:
        def __init__(self, x: int, next: 'Node' = None, random: 'Node' = None):
            self.val = int(x)
            self.next = next
            self.random = random
    """
    
    class Solution:
        def copyRandomList(self, head: 'Node') -> 'Node':
            """
            原结点后增加副本->补充副本的random->副本拆分出来
            """
            if not head:
                return head
            # 原结点后增加副本
            p = head
            while p:
                node = Node(p.val)
                node.next = p.next
                p.next = node
                p = p.next.next
            # 补充副本的random
            p = head
            while p:
                p.next.random = p.random.next if p.random else None
                p = p.next.next
            # 副本拆分出来
            p1 = head
            head2 = p2 = head.next
            while p2.next:
                p1.next = p2.next
                p2.next = p2.next.next
                p1 = p1.next
                p2 = p2.next
            return head2

    【Leetcode-141】

    一、题目:两两交换链表中的节点

      给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。

      你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

    二、代码:

    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, val=0, next=None):
    #         self.val = val
    #         self.next = next
    class Solution:
        def swapPairs(self, head: ListNode) -> ListNode:
            """
            每次走两步,交换2节点,若步数不到2则不交换
            """
            dummy = ListNode()
            dummy.next = head  # 哑节点,避免处理头
            p = dummy  # p指向处理完成的节点
            # 0-1-2-3..,p开始指向0
            while p.next and p.next.next:  
                tmp = p.next.next  # tmp=2
                p.next.next = tmp.next  # 1-3
                tmp.next = p.next  # 2-1
                p.next = tmp  # 0-2
                p = p.next.next
            return dummy.next

    【Leetcode-141】

    一、题目:环形链表

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

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

      如果链表中存在环,则返回 true 。 否则,返回 false 。

    二、代码:

    # 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:
            p1 = p2 = head
            while p2 and p2.next:
                p1 = p1.next
                p2 = p2.next.next
                if p1 == p2:
                    return True        
            return False

    【Leetcode-142】

    一、题目:环形链表2

      给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

      为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意,pos 仅仅是用于标识环的情况,并不会作为参数传递到函数中。

      说明:不允许修改给定的链表。

      进阶:

      你是否可以使用 O(1) 空间解决此题?

    二、代码:

    class Solution:
        def detectCycle(self, head: ListNode) -> ListNode:
            p1 = p2 = head
            flag = False  # 无环
            while p2 and p2.next:
                p1 = p1.next
                p2 = p2.next.next
                if p1 == p2:
                    flag = True  # 有环
                    break
            if flag:
                p2 = head
                while p1 != p2:
                    p1 = p1.next
                    p2 = p2.next
                return p1
            else:
                return None

    【Leetcode-146】

    一、题目:LRU缓存机制

    二、代码:

    class ListNode:
        def __init__(self, key=None, value=None):
            self.key = key
            self.value = value
            self.pre = None
            self.next = None
    
    class LRUCache:
    
        def __init__(self, capacity: int):
            self.capacity = capacity
            self.hashmap = {}
            self.head = ListNode()
            self.tail = ListNode()
            self.head.next = self.tail
            self.tail.pre = self.head
    
        def move_to_head(self, node):
            # 从原位置拆出来,放到开头
            node.pre.next = node.next
            node.next.pre = node.pre
            self.insert_to_head(node)
            
        def insert_to_head(self, node):
            node.next = self.head.next
            self.head.next.pre = node
            node.pre = self.head
            self.head.next = node
    
        def get(self, key: int) -> int:
            if key in self.hashmap:
                node = self.hashmap[key]
                self.move_to_head(node)
                return node.value
            else:
                return -1
    
        def put(self, key: int, value: int) -> None:
            if key in self.hashmap:
                self.hashmap[key].value = value
                node = self.hashmap[key]
                self.move_to_head(node)
            else:
                if len(self.hashmap) == self.capacity:
                    # 在尾部删除一个节点
                    del_node = self.tail.pre
                    del_node.pre.next = self.tail
                    self.tail.pre = del_node.pre
                    del self.hashmap[del_node.key]
                node = ListNode(key, value)
                self.hashmap[key] = node
                self.insert_to_head(node)
    
    
    # Your LRUCache object will be instantiated and called as such:
    # obj = LRUCache(capacity)
    # param_1 = obj.get(key)
    # obj.put(key,value)

    【Leetcode-148】

    一、题目:排序链表

      给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。

      进阶:

      你可以在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序吗?

    二、代码:

    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, val=0, next=None):
    #         self.val = val
    #         self.next = next
    class Solution:
        def sortList(self, head: ListNode) -> ListNode:
            def my_sort(root):
                # 在中间拆分
                if not root or not root.next:
                    return root
                p1, p2 = root, root.next
                while p2 and p2.next:
                    p1 = p1.next
                    p2 = p2.next.next
                # 截断
                left = root
                right = p1.next
                p1.next = None
                # 分别排序
                left = my_sort(left)
                right = my_sort(right)
                # 合并
                pre = p = ListNode(0)
                p1, p2 = left, right
                while p1 or p2:
                    v1 = p1.val if p1 else float('inf')
                    v2 = p2.val if p2 else float('inf')
                    if v1 < v2:
                        p.next = p1
                        p1 = p1.next
                    else:
                        p.next = p2
                        p2 = p2.next
                    p = p.next
                return pre.next
    
            root = my_sort(head)
            return root

    【Leetcode-160】

    一、题目:相交链表

      编写一个程序,找到两个单链表相交的起始节点。

    二、代码:

    # 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:
            p1, p2 = headA, headB
            while p1 or p2:
                if p1 == p2:
                    break
                p1 = p1.next if p1 else headB
                p2 = p2.next if p2 else headA
            return p1

    【Leetcode-206】

    一、题目:反转链表

      反转一个单链表。

    二、代码:

    # 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:
            pre = None
            p = head
            while p:
                tmp = p.next
                p.next = pre
                pre = p
                p = tmp
            return pre
    博文转载请注明出处。
  • 相关阅读:
    Orchard源码分析(4.3):Orchard.Events.EventsModule类(Event Bus)
    Orchard源码分析(4.2):Orchard.Logging.LoggingModule类
    Orchard源码分析(4.1):Orchard.Environment.CollectionOrderModule类
    Orchard源码分析(4):Orchard.Environment.OrchardStarter类
    Orchard源码分析(3):Orchard.WarmupStarter程序集
    Orchard源码分析(2):Orchard.Web.MvcApplication类(Global)
    MSSQL
    MSSQL
    C#、WinForm、ASP.NET
    C#、WinForm、ASP.NET
  • 原文地址:https://www.cnblogs.com/EstherLjy/p/14608024.html
Copyright © 2011-2022 走看看