6月5号和6月6号: 链表相关题目整理 以及 heapq python 小顶堆模块的熟悉与使用...

本文介绍了Python中链表题的解题思路,包括删除链表倒数第N个节点和合并两个有序链表,并探讨了如何优化合并K个升序链表的解决方案,涉及哑节点、双指针和堆排序等技巧。通过实例代码详细解释了每个步骤,适合初学者巩固链表操作和算法设计。
摘要由CSDN通过智能技术生成

6月5号的题目是一道链表题,非常简单,但是却可以显示出链表题目做法的相关思路,这边是先要推荐一个blog照着这个人的博客练习效果非常不错。

https://blog.csdn.net/weixin_42723548/article/details/97921980?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.control

然后是一贯的一开始的tip:哑节点和指针:tmp和res指向的是存储 哑节点0 的位置,此时tmp和res存储的是同一内存地址,可以理解成tmp和res是两个指针。当对res进行操作时,会在res中存储内容(节点)即为这个内存放内容。而res不断移动,tmp还是指向原来的 哑节点的位置。

特别提醒:

#在python里面移动两个节点的公式:
while p.next and p.next.next:
   p = p.next.next



题目:第一类,python删除题目:

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: ListNode, n: int) -> ListNode:
        dummy = ListNode(0)#建立哑节点
        dummy.next = head
        #双指针问题
        #两个指针差n个距离
        left = dummy
        right = left
        for i in range(n):
            right=right.next
        while right.next:
            left=left.next
            right=right.next
        tmp = left.next.next
        left.next=tmp
        return dummy.next



这道题目一次遍历需要用到双指针和哑节点:注意最后的return dummy.next 可以很好地处理边界情况。

21. 合并两个有序链表

#         self.val = val
#         self.next = next
class Solution:
    def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
        dummy = ListNode(0)
        # if l1.val>l2.val:
        #     dummy.next=l1
        # else: dummy.next=l2
        q=dummy
        p1,p2 = l1,l2
        while p1 and p2:
            if p1.val<p2.val:
                q.next = p1
                p1=p1.next
            else:
                q.next=p2
                p2=p2.next
            q=q.next
        if p1: q.next=p1
        else: q.next=p2
        return dummy.next




哑节点做,本质上是一个插入题

接下来,来做这个题目的进阶版本

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 delete(lists):
            del_list= []
            for idx,node in enumerate(lists):
                if node:
                    del_list.append(node)
            return del_list
        dummy = ListNode(0)
        q = dummy
        lists = delete(lists)
        while lists:
            min_idx,minnode = 0, lists[0]
            for idx,node in enumerate(lists):
                if node.val < minnode.val:
                    minnode = node
                    min_idx=idx
            q.next = minnode
            lists[min_idx] = lists[min_idx].next
            q=q.next
            lists = delete(lists)
        return dummy.next



这里是一开始的思路,但是超时间了,主要的问题是找最小用时太多了,这个时候最快的方法是动态维护一个堆结构

这里应该是一个小顶堆,关于小顶堆的构建我们用最经典的自下而上建堆,建堆时间复杂度为O(N), siftdown操作的时间复杂度为logn

def sift(li,low,high):
    i = low
    j= 2*i+1
    tmp = li[i]
    while j<=high:
        if j+1<=high and li[j+1]<li[j]:
            j=j+1
        if li[j]<tmp:
            li[i] = li[j]
            i = j
            j=2*j+1
        else:
            break
    li[i] = tmp

def heap_sort(li,k):
    #构建小顶堆
    n= len(li)
    for i in range(n//2-1,-1,-1):
        sift(li,i,n-1)
    topk=[]
    for i in range(k):
        topk.append(li[0])
        li[0] = li[-1]
        li.pop()
        sift(li,0,len(li)-1)
    return topk



这里我首先是要先弄懂堆的原理,然后用python里自带的优先队列 module heapq,在heapq的使用中最重要的一点是要注意heapq的优先级,关于这个python3 cookbook 1.4有着非常清晰的讲解。

from heapq import *
class Solution:
    def mergeKLists(self, lists: List[ListNode]) -> ListNode:
        
        heap=[]
        #首先先建立一个堆
        for idx,node in enumerate(lists):
            if node:
                heappush(heap,(node.val,idx,node))
                #lists[idx] = lists[idx].next
        dummy = ListNode(0)
        q = dummy
        while heap:
            _ ,idx,cur = heappop(heap)
            q.next=cur
            q=q.next
            if cur.next:
                heappush(heap,(cur.next.val,idx,cur.next))
        return dummy.next



稍微熟悉了一下heapq的操作。今天就这样吧

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值