Leetcode链表

本文介绍了链表的基本概念,包括单链表、双链表和循环链表。详细讲解了如何移除链表元素、设计链表结构、反转链表、两两交换链表节点以及删除链表的倒数第N个节点。此外,还探讨了相交链表的查找和环形链表的检测方法。最后,提到了LRU缓存的实现,利用双链表结合哈希表来优化存储策略。
摘要由CSDN通过智能技术生成

目录

链表基础知识

  1. 定义:链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成数据域指针域最后一个节点的指针域指向None(空指针的意思)。
    链表的入口节点称为链表的头结点也就是head
  2. 分类:单链表、双链表、循环链表
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

203 移除链表元素

在这里插入图片描述

# 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]:
        dummy = ListNode(0,head)  # 哑结点
        p = dummy  # 指针
        while p.next != None:  # 只要下一个不为空则一直进行
            if p.next.val == val:  # 下一个的val等于目标值
                p.next = p.next.next  # 通过对next赋值实现删除元素
            else:  # 下一个的val不等于目标值:指针移动
                p = p.next
        return dummy.next


707 设计链表

在这里插入图片描述

class MyLinkedList:
    def __init__(self):  # 列表需要虚拟头结点和链表长度(不包括虚拟结点)
        self.head = ListNode()  # 设置虚拟头结点
        self.size = 0  # 列表长度

    def get(self, index: int) -> int:
        if index<0 or index>=self.size:
            return -1            
        cur = self.head
        for _ in range(index+1):
            cur = cur.next
        return cur.val

    def addAtHead(self, val: int) -> None:
        new = ListNode(val,self.head.next)
        self.head.next = new
        self.size += 1  # 注意改变size
        '''
        i = self.head  # 用于debug 输出链表
        while i != None:
            print(i.val)
            i = i.next
        '''

    def addAtTail(self, val: int) -> None:
        cur  = self.head
        while cur.next:  # 若下一个指向空 则终止 进行添加
            cur = cur.next
        cur.next = ListNode(val)
        self.size += 1

    def addAtIndex(self, index: int, val: int) -> None:
        if index<=0:
            self.addAtHead(val)
        elif index==self.size:
            self.addAtTail(val)
        elif index>0 and index<self.size:
            cur = self.head
            for _ in range(index):
                cur = cur.next
            temp = cur.next
            cur.next = ListNode(val,temp)
            self.size += 1

    def deleteAtIndex(self, index: int) -> None:
        if index>=0 and index<self.size:
            cur = self.head
            for _ in range(index):
                cur = cur.next
            cur.next = cur.next.next
            self.size -= 1

class ListNode:
    def __init__(self,val=0,next=None):
        self.val = val
        self.next = next


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: Optional[ListNode]) -> Optional[ListNode]:
        pre = None
        cur = head
        while cur:  # 快指针非空
            temp = cur.next
            cur.next = pre
            pre = cur
            cur = temp
        return pre



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 = ListNode(0,head)
        temp = dummy
        while temp.next != None and temp.next.next!=None:
            node1 = temp.next
            node2 = temp.next.next
            temp.next = node2
            node1.next = node2.next
            node2.next = node1
            temp = node1
        return dummy.next


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 = ListNode(0,head)
        s = f = dummy
        for _ in range(n):
            f = f.next  # 提前走n步
        while f.next!=None:
            s = s.next
            f = f.next
        s.next = s.next.next
        return dummy.next


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) -> Optional[ListNode]:
        a = headA
        b =headB
        while a or b: # 都为空则结束
            if a==b:
                return a

            if a:  # a没到末端
                a = a.next
            else:
                a = headB

            if b:  # b没到末端
                b = b.next
            else:
                b = headA
        return 


142 环形链表Ⅱ

在这里插入图片描述

分析:快慢指针

在这里插入图片描述

# 快慢指针
# 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]:
        dummy = ListNode(0,head)
        s = f = dummy
        while f.next != None and f.next.next != None:
            f = f.next.next
            s = s.next
            if f == s:
                s = dummy
                while s != f:
                    s = s.next
                    f = f.next
                return s
        return

146. LRU 缓存(双链表结合哈希表)

在这里插入图片描述

分析:

class DLinkedNode:
    def __init__(self, key = 0, value = 0):
        self.key = key  # 为了能在哈希表中找到链表中被删除的节点
        self.value = value
        self.pre = None  # 双向链表  无需遍历就可以找到当前节点的前一个结点地址
        self.next = None

class LRUCache:
    def __init__(self, capacity: int):
        self.head = DLinkedNode()
        self.tail = DLinkedNode()
        self.head.next = self.tail
        self.tail.pre = self.head
        self.hp = {}  # 初始化一个哈希表
        self.capacity = capacity
        self.size = 0

    def get(self, key: int) -> int:
        if key not in self.hp:           
            return -1
        node = self.hp[key]
        self.moveToHead(node)
        return node.value

    def put(self, key: int, value: int) -> None:
        if key in self.hp:
            node = self.hp[key]
            self.moveToHead(node)
            node.value = value
        else:
            node = DLinkedNode(key, value)
            self.hp[key] = node
            self.addToHead(node)
            self.size += 1
            if self.size>self.capacity:
                removedTail = self.removeTail()
                del self.hp[removedTail.key]  # 只有节点有属性key才能从字典中找到并删除
                self.size -= 1         

    def moveNode(self, node):
        node.pre.next = node.next
        node.next.pre = node.pre

    def moveToHead(self, node):  # 将节点移到头部等于先将节点移除,再将节点添加到头部
        self.moveNode(node)
        self.addToHead(node)

    def addToHead(self, node):
        headnext = self.head.next
        self.head.next = node
        node.next = headnext
        node.pre = self.head
        headnext.pre = node

    def removeTail(self):
        node = self.tail.pre
        '''
        node.pre.next =  self.tail
        self.tail.pre = node.pre
        '''
        self.moveNode(node)
        return node

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[Optional[ListNode]]) -> Optional[ListNode]:
        def merge2Lists(l1, l2):
            dummyhead = ListNode(0)
            cur = dummyhead
            while l1 and l2:  # 链表非空   
                if l1.val <= l2.val:
                    cur.next = l1  
                    cur = l1  # 当前指针移动
                    l1 = l1.next  # l1移动
                else:
                    cur.next = l2
                    cur = l2
                    l2 = l2.next
            if not l1:  # l1 为空
                cur.next = l2
            else:
                cur.next = l1
            return dummyhead.next


        n = len(lists) 
        temp = []       
        if n == 0:
            return 
        if n == 1:
            return lists[0]  # 返回地址  不能直接返回lists
        if n == 2:
            return merge2Lists(lists[0], lists[1])
        for i in range(0, n, 2):
            if i == n-1:  # 说明n为奇数
                temp.append(lists[i])
            else:
                temp.append(merge2Lists(lists[i], lists[i+1]))
        return self.mergeKLists(temp)

# 时O(kn×logk)  其中n是单个链表长度,k是链表数目,(每次合并两个链表,以第一次合并为例,合并两链表时间为O(2n),总共进行k/2次,所以为O(nk)
# 空O(logk) 递归深度
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值