代码随想录算法训练营Day3

代码随想录算法训练营Day3

力扣203.移除链表元素、707.设计链表、206.反转链表

一、链表和数组的联系与区别

特性数组链表
存储方式连续存储离散存储
随机访问 O ( 1 ) O(1) O(1) O ( n ) O(n) O(n)
插入/删除 O ( n ) O(n) O(n)头部、中间; O ( 1 ) O(1) O(1)尾部 O ( 1 ) O(1) O(1)头部、中间,已知位置
内存分配一次性分配连续内存按需分配节点内存
内存开销无额外开销每个节点有指针开销
适用场景随机访问频繁、数据大小固定插入删除频繁、数据大小动态变化

二、力扣203-移除链表元素【easy】

题目链接:力扣203-移除链表元素
题目
视频链接:代码随想录

1、思路

  • 头节点和非头节点的删除处理方式不一致。
  • 引入虚拟头节点,变成统一规则删除。
    • 涉及到对链表修改(如插入、删除、移动),都可以使用虚拟头节点。
  • 时间复杂度: O ( n ) O(n) O(n)

2、代码

class Solution:
    """
    创建虚拟节点,统一处理删除所有节点规则
    时间复杂度:O(n)
    """
    def removeElements(self, head: Optional[ListNode], val: int) -> Optional[ListNode]:
        dummy_head = ListNode(next = head) #创建一个新的 ListNode 对象,并将指针next初始化为指向另一个链表节点(head)。
        current = dummy_head

        # 遍历列表并删除值为val的节点
        while current.next: #只要当前节点的下一节点存在,循环将会继续遍历
            if current.next.val == val:
                current.next = current.next.next
            else:
                current = current.next
        return dummy_head.next  #返回的不是head,避免了如果head = val 的情况

3、代码的问题

  • ListNode:创建一个新的节点,默认它的指针指向None
  • Optional[ListNode] :表示 head可以是一个 ListNode 类型的对象,也可以是 None(即链表为空)

三、力扣707-设计链表【medium】

题目链接:力扣707-设计链表题目> 视频链接:代码随想录

1、思路

  • 五种操作

    • 获取下标为index的节点的值:get

    • 头部插入一个值为val的节点:addAtHead

      • 在这里插入图片描述
    • 尾部插入一个值为val的节点:addAtTail

      • 在这里插入图片描述
    • 将一个值为val的节点插入到链表中下标为index的节点之前:addAtIndex

      • 在这里插入图片描述
    • 删除下标为index的节:deleteAtIndex

      • 在这里插入图片描述
  • index是从0开始

  • 当链表发生变化时,记得更新size值。

  • 重点是插入、删除,这个时候需要找到被删除(或者是插入位置)元素的前驱元素,然后修改next的值。

2、代码

class MyLinkedList:

    def __init__(self):
        self.dummy_head = ListNode() #指向None
        self.size = 0
    
    """
    获取节点
    """  
    def get(self, index: int) -> int: 
        if index < 0 or index >= self.size:
            return -1
        current = self.dummy_head.next #在链表非空的情况下,self.dummy_head.next 指向链表的第一个实际节点。
        for i in range(index):
            current = current.next
        return current.val

    """
    头部插入节点
    """     
    def addAtHead(self, val: int) -> None:
        self.dummy_head.next = ListNode(val , self.dummy_head.next)#更改虚拟节点的指针;创建一个新的 ListNode 节点对象,其值为 val,next 指针指向当前虚拟头节点的下一个节点(即原来的链表头节点)
        self.size +=1
        
    """
    尾部插入节点
    """ 
    def addAtTail(self, val: int) -> None:
        current = self.dummy_head
        while current.next:
            current = current.next
        current.next = ListNode(val) 

        self.size +=1

    """
    将一个值为 val 的节点插入到链表中下标为 index 的节点之前
    """ 
    def addAtIndex(self, index: int, val: int) -> None:
        if index < 0 or index > self.size:
            return 
        current = self.dummy_head
        for i in range(index):
            current = current.next
        current.next = ListNode(val , current.next)
        self.size +=1

    """
    删除下标为index的节点
    """ 
    def deleteAtIndex(self, index: int) -> None:
        if index < 0 or index >= self.size:
            return
        current = self.dummy_head
        for i in range(index):
            current = current.next
        current.next =current.next.next
        self.size -= 1

3、代码问题

  • 除了get其他四个的current=dummy_head;而
    getcurrent=dummy_head.next
  • index的时候要记得判断它是否合法

四、力扣206-反转链表

题目链接:力扣206-反转链表在这里插入图片描述
视频链接:代码随想录

1、思路

在这里插入图片描述

2、代码

  • 双指针法
"""
双指针法
时间复杂度:O(n)
"""
# 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]:
        #Optional 用于明确表示某个变量或函数参数可以接受 None 或指定类型的值。
        cur = head
        pre = None
        while cur: #循环的终止条件是cur=None
            temp = cur.next #临时储存
            cur.next = pre #反转
            #是先赋值pre再赋值cur
            pre = cur 
            cur = temp
        return pre #最后pre是反转链表的头节点
        
  • 递归法
"""
递归法
时间复杂度:O(n)
"""
# 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]:
        return self.reverse(head,None) #入口调用启动了递归过程,逐步反转链表
    def reverse(self,cur:Optional[ListNode],pre:Optional[ListNode]):
        if cur == None:
            return pre
        temp = cur.next #临时储存
        cur.next = pre #反转
        return self.reverse(temp,cur)

3、代码问题

  • Optional 用于明确表示某个变量或函数参数可以接受 None 或指定类型的值。
  • 是先赋值pre再赋值cur;顺序很重要
  • 返回的是pre是反转链表的头节点
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值