链表定义:
很多时候链表没有给出,要自己定义,所以一定还要掌握怎么定义链表。
class ListNode():
def __init__(self, val = 0, next = None):
self.val = val
self.next = next
链表内存不是连续存储的,从上一个找下一个node就用next去找。查找较为复杂,为O(n)。
203.移除链表元素
这道题是考察链表的最基础操作。个人感觉主要让我们熟悉两个思想:1.虚拟头结点应用:在维护链表时,其中每一个元素会被操作,比如删除,删除除了头结点之外的结点只需要将前一个连到后一个就行,但是头结点它没有前一个结点。如果没有虚拟头结点操作要单独考虑删除头部,此时加入一个没用的头结点会使操作统一。这个虚拟头结点在很多时候都很有用。 2.链表指针:整个链表操作都是在维护一个链表,而一般题目都要返回头结点(知道头结点就相当于知道整个链表),此时一般需要用一个指针保存头结点,而用另一个指针去操作,这就是tmp的作用。题解如下:
707.设计链表
一道思路上很简单但是十分考察细节的题目,也是虚拟头结点非常好用的一道题。我之前也尝试不用虚拟头结点,但是发现删除那里很麻烦,并且循环和索引值总是对不上,每次都差1,看着不够简洁,因此还是使用了虚拟头结点。
首先要自己定义一个链表(本次用单链表):
属性定义里面需要一个虚拟头结点和一个链表长度(在get里面很好用):
get函数首先要判断是否合法,然后直接搜索就可以了:
三个插入函数比较类似,很多题解中头部尾部插入都用定点插入写了,我这里觉得插头部很简单,就直接写了 ,然后在定点插入里面用插入头部函数:
删除的话要先判断合法性,可以借用get,然后这里就会发现虚拟头很好用:
206.反转链表
递归法:递归有两种写法,一个是自顶向下,一个是自底向上。区别在于从开头处理还是从后面处理。
自顶向下:这个方法是把第一个和后面全部交换,然后后面全部进行一样的操作。例如12345,那么第一步就是变成23451,然后2345再进行反转,依此类推。
自底向上:这个方法类似,只是先变成51234,再把1234进行同样变化
迭代法:迭代和自顶向下的递归思路类似,只是用循环来代替递归。对于python来说不用一个变量来存,可以直接交换数值,这样会简洁很多:
其它:
学习时长:3h
学习心得:递归有点忘了,正好复习一下
学习链接:链表基础知识, 移除链表元素, 设计链表, 反转链表