Day03 - 链表 203 707 206

链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域一个是指针域,最后一个节点的指针域指向null。

  • 单链表中的指针域只能指向节点的下一个节点。
  • 双链表:每一个节点有两个指针域,一个指向下一个节点,一个指向上一个节点。
    (既可以向前查询也可以向后查询)
  • 循环链表,顾名思义,就是链表首尾相连。

链表中的节点在内存中不是连续分布的 ,而是散乱分布在内存中的某地址上。

要注意链表的节点是如何定义的,要能手撕。

Python定义链表

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

203. 移除链表元素

哈哈不会写链表,之前上学就不会写。
直接看答案了。
语法:原来
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
这个是说已经定义好了不用再定义了的意思,我还以为这只是个提示呢

看完答案,真是好简单的语法,虽然有些好奇不用虚拟头结点会是什么样呢?

第二遍写:
算法理解错误:要明白dummy_head是头节点,cur是目前节点,这就是我们一直在操作cur节点但最后返回的是dummy_head的原因。
语法错误:Python中没有NULL,只有None

第三遍写:
算法理解错误:最后忘记把虚拟头结点去掉了,应该返回的是dummy_head.next
 

第四遍写正确。

707. 设计链表

隔了几天再来看,其实考的是链表的不同操作如何实现。大概抄了一遍,不打算背了,实际用可能会用LinkedList类,先把时间放在常考题目上。

206. 反转链表

看起来简单!

常考题目。

算法要点:这里没有使用虚拟头结点。想到前几天群里也有人问这个事情:“一般涉及到增删改操作,用虚拟头结点会方便很多。如果只用查的话,用不用都差别不大。”

算法技巧,常见解题思路:
这里一共有pre cur temp三个指针,所以查了一下这个解法为什么叫双指针:

双指针技巧可细分分为两类,一类是快慢指针,一类是左右指针。

前者解决主要解决链表中的问题,比如典型的判定链表中是否包含环、反转链表、找链表的中间节点、删除链表的倒数第 N 个结点;也用来解决数组中的问题,如移动/移除元素、删除有序数组中的重复项。

后者主要解决数组(或者字符串)中的问题,比如二分查找,滑动窗口。

那么这一题用到的就是快慢指针。

可以养成这样的思路:
链表 → 快慢指针
数组 → 左右指针

坦白讲我一开始的思路是获取链表长度,然后从最后一个开始处理。不过看起来大家都解法都是从链表的第一个开始往后处理。回家问问为什么不能那样写。

算法要点:注意都是先操作然后移动指针

第二遍写双指针:正确

这道题递归快一点点,但是内存消耗多很多。

在其他问题里,递归并不一定比双指针更快,双指针在很多线性扫描问题中更有效率。

递归的内存消耗大,主要是因为递归调用会占用调用栈的内存,且需要同时处理每次递归的结果。

第二遍写递归:
语法错误:递归写法是self.___(...)
为什么这里要加self? Java好像直接写方法名就可以了。

第三遍写递归:
注意cur == None不要写成cur == 0。

第四遍写递归没什么大问题了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值