数据结构与算法1: 链表

基础知识

链表可以被想象为一系列的节点,每个节点至少有一个指针指向下一个节点,在最后一个节点,用null pointer来表示链表的结束。

链表的创建速度通常很快,在表头和表尾的插入也很快(O(1)),但是销毁和搜索查找则很慢(O(n))。

解题技巧

PreNode的使用

题目: . - 力扣(LeetCode)

介绍: 在链表中,经常会通过在链表前面插入一个节点的形式,来让之后的讨论变得简单。比如下面的这道题, 由于对于节点进行两两交换,将会造成head节点的更换,如果利用prenode,可以避免复杂的分类讨论。

# 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]:
        cur_node = ListNode()
        cur_node.next = head
        pre_node = cur_node

        while(cur_node  and cur_node.next and cur_node.next.next):
            next_node = cur_node.next
            next2node = next_node.next
            cur_node.next = next2node
            tmp_node = next2node.next

            next2node.next = next_node
            next_node.next = tmp_node

            cur_node = next_node
        return pre_node.next

快慢指针,链表反转

题目名称: 重排链表

链接: ​​​​​​. - 力扣(LeetCode)

介绍:本题的目标是将链表进行重新组合,如下图。

如果按照标准的解法,我们需要实现三步

1. 链表中点的获取

2. 链表的反转

3. 链表的插入

而每一步都是比较经典的链表操作。

首先,为了获取链表中点,我们可以通过快慢链表。

def getMidNode(head: ListNode)->ListNode:
    fast_node = head
    slow_node = head
    while(fast_node.next.next and slow_node.next):
        fast_node = fast_node.next.next
        slow_node = slow_node.next
        return slow_node

然后,我们需要进行链表的反转。

def reverseList(head: ListNode)->ListNode:
            prev_node = None
            cur_node = head
            while(cur_node):
                next_node = cur_node.next
                cur_node.next = prev_node

                prev_node = cur_node
                cur_node = next_node
            return prev_node

其中需要注意的是,我们要存储prev_node, next_node; 在while循环中,我们每次需要判断cur_node, 但是更重要的是,在最后一次,cur_node必然为空,因此,最后需要返回的是prev_node.

最后,我们需要实现列表的融合。

对应的就是 A--> B  和 C--> D, 变为 A-->C --> B --> D . 为了实现这一操作, 我们每次需要对于两个链表的next node进行备份,然后再更改current node的相互关系,然后再去处理next node。

def mergeLists(headA:ListNode, headB:ListNode):
            curA = headA
            curB = headB

            while(curA and curB):
                tmpA = curA.next
                tmpB = curB.next

                curA.next = curB
                curB.next = tmpA

                curA = tmpA
                curB = tmpB
            return headA

实现了这些子模块后,我们经过整合,就可以实现最后的功能。为了把两个链表进行拆分,我们需要将中间节点的next在备份之后,设定为0。

midNode = getMidNode(head)

        headA = head
        headB = midNode.next
        midNode.next = None
        headB = reverseList(headB)
        result = mergeLists(headA, headB)

        return result

分而治之 divide and conquer

参考链接: 23. 合并 K 个升序链表

这题同样经典,将多个链表合并的问题,通过对于list的长度的判断,进行分而治之。基本单元是对于两个链表进行排序和和合并,这考验的是链表的基本功。

class Solution:
    def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
        def mergeTwoLists(headA, headB):
            head = ListNode()
            cur_node = head
            while(headA and headB):
                if(headA.val <= headB.val):
                    tmp = headA.next
                    cur_node.next = headA
                    cur_node = headA
                    headA = tmp
                else:
                    tmp = headB.next
                    cur_node.next = headB
                    cur_node = headB
                    headB = tmp
            if(headA):
                cur_node.next = headA
            elif(headB):
                cur_node.next = headB
            return head.next
        
        n = len(lists)
        if n == 0: return None
        if n == 1: return lists[0]
        left =  self.mergeKLists(lists[:n//2])
        right = self.mergeKLists(lists[n//2:])
        return mergeTwoLists(left, right)

参考链接:

https://www.cs.princeton.edu/courses/archive/spr11/cos217/lectures/08DsAlg.pdf

数据结构学习①--链表_ptr.next = l1 || l2; ptr = ptr.next;-CSDN博客

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值