【leetcode22-36】链表

160.相交链表

在这里插入图片描述

【等比例法】
class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> Optional[ListNode]:
        if not headA or not headB:
            return None
        pointA = headA
        pointB = headB

        while pointA != pointB:
            pointA = pointA.next if pointA else headB  #如果 pointA 是 None,那么 pointA 应该被重新设置为 headB。
            pointB = pointB.next if pointB else headA
        return pointA
class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        lenA = self.getLength(headA)
        lenB = self.getLength(headB)
        
        # 通过移动较长的链表,使两链表长度相等
        if lenA > lenB:
            headA = self.moveForward(headA, lenA - lenB)
        else:
            headB = self.moveForward(headB, lenB - lenA)
        
        # 将两个头向前移动,直到它们相交
        while headA and headB:
            if headA == headB:
                return headA
            headA = headA.next
            headB = headB.next
        
        return None
    
    def getLength(self, head: ListNode) -> int:
        length = 0
        while head:
            length += 1
            head = head.next
        return length
    
    def moveForward(self, head: ListNode, steps: int) -> ListNode:
        while steps > 0:
            head = head.next
            steps -= 1
        return head

206.反转链表

在这里插入图片描述

【递归法】
class Solution:
    def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
        return self.reverse(head, None)

    def reverse(self, cur, pre):
        if cur == None:
            return pre
        temp = cur.next
        cur.next = pre
        return self.reverse(temp, cur)
class Solution:
    def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
        cur = head
        pre = None
        while cur :
            temp = cur.next
            cur.next = pre
            pre = cur
            cur = temp 
        return pre

234.回文链表

在这里插入图片描述

class Solution:
    def isPalindrome(self, head: Optional[ListNode]) -> bool:
        #1.先把链表值,都撞到数组里面
        #2.头指针和尾巴指针,同时跑,看看值是否相等
        lists = []
        cur = head
        while cur:
            lists.append(cur.val)
            cur = cur.next
 #下面可以用 return lists == lists[::-1]直接代替
        left, right = 0, len(lists)-1
        while left<= right:
            if lists[left] != lists[right]:
                return False
            left += 1
            right -= 1
        return True

141.环形链表【快慢指针】

在这里插入图片描述

注意:是先让快慢指针跑起来,再看,快慢指针是否会相遇

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

142.环形链表||【快慢指针\集合法】

在这里插入图片描述

没有交点,返回的是 None

class Solution:
    def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
        fast = slow = head
        while fast and fast.next:
            fast = fast.next.next
            slow = slow.next
            #如果有环,slow和fast会相遇
            if fast == slow:
                slow = head  #一个指针在head,一个指针在相遇处
                while slow != fast:
                    slow = slow.next
                    fast = fast.next
                return slow   #此时,slow和fast都在入环的第一个节点
        return None
集合法
class Solution:
    def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
        visited = set()
        while head:
            if head in visited:
                return head
            else:
                visited.add(head)
                head = head.next
        return None

21.合并两个有序链表【递归】

在这里插入图片描述

class Solution:
    def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
        if list1 is None: return list2
        if list2 is None: return list1

        if list1.val <= list2.val:
            list1.next = self.mergeTwoLists(list1.next, list2)
            return list1   #注意这里要有return
        else:
            list2.next = self.mergeTwoLists(list2.next, list1)
            return list2   #注意这里要有return
class Solution:
    # 21. 合并两个有序链表
    def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
        cur = dummy = ListNode()  # 用哨兵节点简化代码逻辑
        
        while list1 and list2:
            if list1.val < list2.val:
                cur.next = list1  # 把 list1 加到新链表中
                list1 = list1.next
            else:  # 注:相等的情况加哪个节点都是可以的
                cur.next = list2  # 把 list2 加到新链表中
                list2 = list2.next
            cur = cur.next
            
        cur.next = list1 if list1 else list2  # 拼接剩余链表
        return dummy.next

【难!】2.两数相加

在这里插入图片描述
在这里插入图片描述

方法二:迭代,初始化一个空链表,每次循环,往链表的末尾添加一个节点
方法一:递归

class Solution:
    def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
        cur = dummy = ListNode()  #哨兵节点,否则第一次循环,无法在一个空节点末尾添加节点
        carry = 0  #进位
        while l1 or l2 or carry:
            carry += (l1.val if l1 else 0) + (l2.val if l2 else 0)  #节点值和进位值 加在一起
            cur.next = ListNode(carry%10)  #每个节点保存一位进位
            carry //= 10  #新的进位
            cur = cur.next  #下一个节点
            if l1: 
                l1 = l1.next #下一个节点
            if l2:
                l2 = l2.next #下一个节点
        return  dummy.next
class Solution:
    # l1 和 l2 为当前遍历的节点,carry 为进位
    def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode], carry=0) -> Optional[ListNode]:
     # 递归边界:l1 和 l2 都是空节点
        if l1 is None and l2 is None: 
            return ListNode(carry) if carry else None  # 如果进位了,就额外创建一个节点
    # 确保l1不空,否则l1.val会报错
        if l1 is None: 
        	l2, l1 = l1, l2
        carry += (l1.val ) + (l2.val if l2 else 0)  # 节点值和进位加在一起
        l1.val = carry % 10  # 每个节点保存一个数位
        l1.next = self.addTwoNumbers(l1.next , l2.next if l2 else None, carry // 10)  # 进位
        return l1

19.删除链表的倒数第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: Optional[ListNode], n: int) -> Optional[ListNode]:
        
        dummy_head = ListNode(next = head)
        fast = dummy_head
        for i in range(n+1):
            fast = fast.next
        slow = dummy_head
        while fast:
            fast = fast.next
            slow = slow.next
        slow.next= slow.next.next
        return dummy_head.next

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

在这里插入图片描述

# 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: Optional[ListNode]) -> Optional[ListNode]:
        dummy_head = ListNode(next =head)
        cur = dummy_head
        while cur and cur.next and cur.next.next:
            temp = cur.next
            temp1 = cur.next.next.next
            cur.next = cur.next.next
            cur.next.next = temp 
            temp.next = temp1
            cur = cur.next.next
        return dummy_head.next

25.K个一组翻转链表【困难】

在这里插入图片描述

class Solution:
    def reverseKGroup(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
    ## 统计节点个数
        cur = head 
        n = 0
        while cur:
            n += 1 
            cur = cur.next

    ## 开始进行K个一组翻转
        dummy_head = ListNode(next = head)
        start = dummy_head   #start-->当前要翻转片段的前一个节点
        pre = None   ##pre  -->表示遍历过的节点,只是为了方便翻转
        cur = head #cur -->指向当前要翻转片段的第一个节点
        while n>= k:
            n -= k 
            for _ in range(k):   #完成k个节点的翻转
                temp = cur.next
                cur.next = pre
                pre = cur
                cur = temp
            temp1 = start.next
            start.next = pre
            temp1.next = cur
            start = temp1
        return dummy_head.next

【难!】138.随机链表的复制

在这里插入图片描述

先拷贝点,在拷贝点和点之间的关系

"""
# 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: 'Optional[Node]') -> 'Optional[Node]':
        if not head :   #如果头结点为空
            return None

        cur = head
        ss = {}   #原始节点和拷贝节点的关系
        while cur:  #复制节点
            ss[cur] = Node(x = cur.val)
            cur = cur.next
        
        cur = head
        while cur: #复制关系
            if cur.next:
                ss[cur].next = ss[cur.next]
            if cur.random:
                ss[cur].random = ss[cur.random]
            cur = cur.next
        return ss[head]  #返回头结点的拷贝节点	

【难!】148.排序链表

在这里插入图片描述

把一个大片段,拆解成0-1个节点,构成的小片段【叶子结点】。然后从树的叶子结点,开始合并
!!!需要注意,要拆解成0-1个结点

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
'''
递归,当只有0个或者1个节点,递归阶数
a=sortList(head)
b=sortList(mid)
在对a和b排序
'''
class Solution:
    def sortList(self, head: Optional[ListNode]) -> Optional[ListNode]:
        if not head or not head.next:
            return head

        slow =  head
        fast = head.next
        while fast and fast.next:
            fast = fast.next.next
            slow = slow.next
        mid = slow.next
        slow.next = None
        
#此时,链表已经被分成 head--slow, mid---链表最后
        left = self.sortList(head)
        right = self.sortList(mid)

#处理单层遍历
        ans = start = ListNode(0)
        while left and right:
            if left.val < right.val:
                start.next = left
                left = left.next
            else:
                start.next = right
                right = right.next
            start = start.next
        start.next = left if left else right  #处理当left或right,有一个不存在

        return ans.next

23.合并K个升序链表【递归+快慢指针】

在这里插入图片描述

时间复杂度:O(nlogk),其中 k 为 lists 的长度,n 为所有链表的节点数之和。每个节点参与链表合并的次数为 O(logk) 次,一共有 n 个节点,所以总的时间复杂度为 O(nlogk)。
空间复杂度:O(logk)。递归深度为 O(logk),需要用到 O(logk) 的栈空间。Python 忽略切片产生的额外空间。

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def mergetwoList(self, list1, list2):
        if not list1: return list2
        if not list2: return list1
        if list1.val < list2.val:
            list1.next = self.mergetwoList(list1.next, list2)
            return list1
        else:
            list2.next = self.mergetwoList(list1, list2.next)
            return list2
    def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
        if len(lists) == 0: return None
        if len(lists) == 1: return lists[0]


        left = self.mergeKLists(lists[0:len(lists)//2])
        right = self.mergeKLists(lists[len(lists)//2:])
        return self.mergetwoList(left, right)

【难!】146.LRU缓存【哈希表+双向链表】

在这里插入图片描述

#哈希表+双向链表
#哈希表,查询时间复杂度O(1)
#双向链表存储顺序
#删除最久未使用的数据时,需要用到链表来确定,要删的结点【即要删,双向链表的头结点】
class Node:
    def __init__(self, key=0, val=0):
        self.key = key
        self.val = val
        self.next = None
        self.pre = None

class LRUCache:
    def __init__(self, capacity: int):
        self.capacity = capacity
        self.hashmap = {}  #【key:node.key】【value:node】
        self.head = Node()  #头结点,仅仅指示位置
        self.tail = Node()   #尾结点,仅仅指示位置
        self.head.next = self.tail
        self.tail.pre = self.head

    def move(self, node):
        node.pre.next = node.next
        node.next.pre = node.pre
    
    def add_to_last(self, node):
        self.tail.pre.next = node
        node.next = self.tail
        node.pre = self.tail.pre
        self.tail.pre = node
    
    def move_to_last(self, node): #把元素从链表移除,并移到链表末尾【表示最近访问过】
        self.move(node)
        self.add_to_last(node)
       
    def get(self, key: int) -> int:
        if key not in self.hashmap:
            return -1 
        node = self.hashmap[key]
        self.move_to_last(node)  #访问了该节点
        return node.val

    def put(self, key: int, value: int) -> None:
        if key in self.hashmap:  # 如果关键字 key 已经存在,则变更其数据值 value
            node = self.hashmap[key]
            node.val = value
            self.move_to_last(node)   #访问了该节点
            return 
        if len(self.hashmap) == self.capacity:  #如果超过容量,还要加节点,则删除头结点之后的节点
            del self.hashmap[self.head.next.key]  #哈希表删掉node.key
            self.move(self.head.next)   #双向链表删掉node

        node = Node(key, value)
        self.hashmap[key] = node
        self.add_to_last(node)
        return
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值