(补)代码随想录算法训练有营DAY3|Leetcode 203、707、206

文章链接:

203. 代码随想录

707. 代码随想录

206. 代码随想录

视频链接:手把手带你学会操作链表 | LeetCode:203.移除链表元素_哔哩哔哩_bilibili

这几天太忙拖欠了好多天,今天先补上day3的内容。

对链表整体不熟悉,基本上每个题都是先看视频(再夸一遍,视频里讲解手撕代码真的很清晰易懂!!!),再自己尝试用python写出来,之后有空要二刷巩固。

203. 移除链表元素

状态:看视频讲解,再自己尝试写

思路:使用虚拟头节点,并引入一个临时指针来遍历链表

总结:

1. 看过视频后,发现单链表结构并不复杂,合理使用虚拟头节点更有助于增删节点

2. cur指针要从dummyhead开始遍历(考虑特殊情况,如head的元素值等于val)

3. return dummyhead.next更准确,因为原先的head,因为有可能已经被删去了

# 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]:
        dummyhead = ListNode(next = head)
        
        cur = dummyhead
        while cur.next:
            if cur.next.val == val:
                cur.next = cur.next.next
            else:
                cur = cur.next

        return dummyhead.next

时间复杂度:O(n)

空间复杂度:O(1)

707. 设计链表

状态:先看视频,再自己做leetcode。只用单链表,中间有多次debug情况

思路:

1. 要先定义一个类ListNode!!使用虚拟头节点,在不同的function中要注意cur指针的初始化

2. 在第n个节点前插入一个节点的关键思路是:只有保证第n个节点是cur.next,才能用cur操作在cur.next前插入一个节点

3. 删去第n个节点的关键思路是:只有保证第n个节点是cur.next,才能将第n个节点的前一个节点(也就是cur)指向第n个节点的后一个节点,从而删去第n个节点

总结:

1. 在获取、增删节点时,要首先判断下标index是否有效。链表的下标是从0开始的,要注意题目要求,以决定何时用判断index > self.size,何时用index >= self.size

2. debug的问题主要出现在:

  • 对cur指针的初始化,何时初始化为cur = self.dummyhead,何时为cur = self.dummyhead.next
  • 何时用判断index > self.size,何时用index >= self.size
    class ListNode:
        def __init__(self, val=0, next=None):
            self.val = val
            self.next = next
    
    class MyLinkedList:
    
        def __init__(self):
            self.dummyhead = ListNode()
            self.size = 0
    
        def get(self, index: int) -> int:
            if index < 0 or index >= self.size:
                return -1
    
            cur = self.dummyhead.next
            for i in range(index):
                cur = cur.next
    
            return cur.val
    
    
        def addAtHead(self, val: int) -> None:
            newnode = ListNode(val=val, next=self.dummyhead.next)
            self.dummyhead.next = newnode
            self.size += 1
    
    
        def addAtTail(self, val: int) -> None:
            cur = self.dummyhead
            while cur.next:
                cur = cur.next
            cur.next = ListNode(val=val,next=None)
            self.size += 1
    
        def addAtIndex(self, index: int, val: int) -> None:
            if index < 0 or index > self.size:
                return
    
            cur = self.dummyhead
            for i in range(index):
                cur = cur.next
    
            cur.next = ListNode(val=val, next=cur.next)
            self.size += 1
    
    
        def deleteAtIndex(self, index: int) -> None:
            if index < 0 or index >= self.size:
                return
    
            cur = self.dummyhead
            for i in range(index):
                cur = cur.next
            cur.next = cur.next.next
            self.size -= 1
    
    
    
    # Your MyLinkedList object will be instantiated and called as such:
    # obj = MyLinkedList()
    # param_1 = obj.get(index)
    # obj.addAtHead(val)
    # obj.addAtTail(val)
    # obj.addAtIndex(index,val)
    # obj.deleteAtIndex(index)

时间复杂度:涉及 index的相关操作为 O(index), 其余为 O(1)

空间复杂度: O(n)

206. 反转链表

状态:先看视频,再自己做leetcode。看完视频就去写代码,很顺畅哈哈。但是需要过段时间二刷巩固

思路:

1. 双指针方法:定义好cur, pre双指针,同时引入临时指针temp;注意对指针赋值时的顺序:用temp保存cur.next; 移动双指针时,先移动pre, 再移动cur。(先将当前的cur赋给pre, 再修改cur为temp)  

时间复杂度:O(n)

空间复杂度:O(1)

2. 递归方法:思路与双指针一致,但要注意递归函数的传入参数赋值

时间复杂度:O(n)

空间复杂度:O(n)

总结:

1. 双指针方法有更易懂,思路更明晰,不过要注意对指针赋值的顺序

2. 递归方法的reverse()函数还可以写成class reverseList的子函数,注意子函数的最后要return reverse()

# 双指针方法
# 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]:
        cur = head
        pre = None
        while cur:
            temp = cur.next
            cur.next = pre
            pre = cur
            cur = temp
        return pre
# 递归方法
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
def reverse(cur, pre):
    if cur == None:
        return pre
    temp = cur.next
    cur.next = pre
    return reverse(temp, cur)

class Solution:
    def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
        return reverse(head, None)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值