代码随想录算法训练营第三天 | 203.移除链表元素 ,707.设计链表,206.反转链表

链表理论基础

https://programmercarl.com/%E9%93%BE%E8%A1%A8%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html

https://programmercarl.com/%E9%93%BE%E8%A1%A8%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html这个结构以前学过一遍,这里复习了一遍怎么在python里面定义链表:

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

203. 移除链表元素

在链表中删除元素主要是更改指针域的指向。第一眼看过去很简单,只要让next指向下一个节点就行;但是看了题解之后发现忽略了头节点的情况。

这里看了一下视频,但是没有太看懂。。看了一下答案之后自己写了一下代码,写出来了(虽然中间出现了一些粗心的小错误)。

class ListNode(object):
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next
class Solution(object):
    def removeElements(self, head, val):
        """
        :type head: ListNode
        :type val: int
        :rtype: ListNode
        """
        dummy_head = ListNode(next=head)
        cur = dummy_head
        while cur.next:
            if cur.next.val == val:
                cur.next = cur.next.next
            else:
                cur = cur.next
        return dummy_head.next

707. 设计链表

题目在这里:https://leetcode.cn/problems/design-linked-list/

感觉要求好多,自己写应该会很费时间,于是直接看答案了。据说这道题包含了链表的所有常规操作,练熟基本上链表就没有问题了~

视频讲解:https://www.bilibili.com/video/BV1FU4y1X7WD/?vd_source=40781b3117fa72cc67da258629107b62

1.获取第n个节点的值

统一使用虚拟头节点,方便对链表进行增删改操作。

先做合法性检查(n的范围)和定义临时指针,然后写while循环,cur想清楚极端情况即n=0的情况就行。

2.头部插入节点

插入节点需要定义一个新的链表节点,即让newnode的next指向head,然后dummyhead的next指向newnode,这里不能颠倒,因为颠倒后第二步就无法操作了(这里画个图就很清楚,因为dummyhead到head的指针消失了,就找不到head了)。

3.尾部插入节点

需要先让cur指向尾部,然后才能在尾部插入节点。终止条件是cur.next变为null。

4.第n个节点前插入节点

cur要指向n-1,第n个节点是cur.next。检查了一下n=0发现没有问题。

5.删除第n个节点

首先对n进行合法性判断,然后开始删节点。

如果要删第n个节点,必须知道前一个节点的指针,因为要修改这个指针到n+1,因此第n个节点一定是cur.next。再检查n=0发现没有问题。

听完我反而感觉非常简单?可能因为之前对链表的结构有一定熟悉度了,而链表的操作无非就是操作指针。说明熟悉还是有用的,数组那里的操作方法我都是第一次见。

写的时候发现自己还是眼高手低了,从第一个函数就卡住了,返回来看了一眼答案,发现leetcode的官网上给的模板没有定义节点就直接定义链表了,跳过了一步,导致链表的size没有定义过。挣扎着写完整个函数之后,随着排bug检查了一堆小问题,比如一开始val和next没有传参,中间self.size没有更新,插入链表的操作没有完成完整的两步,之类的。。最后终于通过了:
 

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


class MyLinkedList(object):
    def __init__(self):
        self.dummyhead=ListNode()
        self.size=0
        
    def get(self, index):
        """
        :type index: int
        :rtype: int
        """
        cur=self.dummyhead.next
        if index <0 or index >= self.size:
            return -1

        for i in range(index):
            cur = cur.next
        return cur.val
                

    def addAtHead(self, val):
        """
        :type val: int
        :rtype: None
        """
        add= ListNode(val=val)
        add.next = self.dummyhead.next
        self.dummyhead.next = add
        self.size += 1


    def addAtTail(self, val):
        """
        :type val: int
        :rtype: None
        """
        add = ListNode(val=val)
        cur=self.dummyhead
        while cur.next:
            cur = cur.next
        cur.next=add
        self.size += 1


    def addAtIndex(self, index, val):
        """
        :type index: int
        :type val: int
        :rtype: None
        """
        if index<=self.size:
            add=ListNode(val=val)
            cur=self.dummyhead
            for i in range(index):
                cur = cur.next
            add.next = cur.next
            cur.next=add
            self.size +=1



    def deleteAtIndex(self, index):
        """
        :type index: int
        :rtype: None
        """
        cur=self.dummyhead
        if index >=0 and index < self.size:
            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)

206. 反转链表

题目链接:https://leetcode.cn/problems/reverse-linked-list/
直接看的答案:https://programmercarl.com/0206.%E7%BF%BB%E8%BD%AC%E9%93%BE%E8%A1%A8.html#%E6%80%9D%E8%B7%AF

里面写其实只需要改变链表的next指针的指向,直接将链表反转 ,而不用重新定义一个新的链表。但是我看了还是觉得蛮抽象的,不知道怎么反转。于是去看了视频:

https://www.bilibili.com/video/BV1nB4y1i7eL/

反转链表是考察基础数据操作的非常好的一题,大厂常考。

双指针法的思路是定义一个cur和一个pre,每一轮都让cur指向pre。递归的写法其实是严格按照双指针的思路来的。

稍微参考了一下答案就写出来了!不过对为什么要return pre不太清楚,于是问了下chatgpt,它说返回头部就相当于返回链表了。

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution(object):
    def reverseList(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        cur = head
        pre = None
        while cur:
            temp = cur.next
            cur.next = pre
            pre = cur
            cur = temp
        return pre

后面又试了一下递归法。当时听的时候就不太懂,直接看答案,然后复现了。研究了一下,其实是把while循环改成了递归,这样每个while循环里的双指针向前走这一步也省去了,就变成了定义起点步骤之后不断重复递归的过程。

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution(object):
    def reverseList(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        return self.reverse(head,None)
    def reverse(self,cur,pre):
        if cur == None: #走到尾节点后一个节点了
            return pre
        temp=cur.next
        cur.next = pre
        return self.reverse(temp,cur)



 

  • 18
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值