链表相关 python
—————剑指offer—————
easy
1)JZ6 从尾到头打印链表
题目描述
*注意输入的是结点,输出的是数组
①方法一:打入栈,逆序输出
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
python3
class Solution:
def printListFromTailToHead(self , listNode: ListNode) -> List[int]:
# write code here 牛客里默认py3的格式
stack = []
while listNode:
stack.append(listNode.val)
listNode = listNode.next
return stack[::-1]
listnode是头节点,List[list]返回一个列表
python2 的默认自定义函数的格式是
class Solution:
def blaba(self, listnode):
liatnode头结点名
②方法二:递归 (但很有可能超过最大递归层数而报错)
class Solution:
def printListFromTailToHead(self , listNode: ListNode) -> List[int]:
# write code here
return self.printListFromTailToHead(listNode.next) + [listNode.val] if listNode else []
注意
Ⅰ 方法自身间的回溯需要 + self
Ⅱ 同一个类,不同对象间的互相调用回溯需要 + self
Ⅲ 方法内的函数递归自身不需要self(如print方法里我再自定义一个函数进行递归便不需要self)
这里的第一参数self表示创建的是类实例
Ⅳ 注意这个if else的使用, blablabla = a 的执行是在if的条件下,否则就 = else里的那个东西
Ⅴ 注意[]与()的使用,第一遍自己打的时候,listnode.val外面写成了(),这样是错的
Ⅵ 注意 + 是拼接的意思
Ⅶ 注意使用递归可能会因为超过最大递归层数而报错,谨慎使用(此题在牛客使用递归没有通过)
2)JZ24 反转链表
题目描述
给定单链表的头节点 head ,请反转链表,并返回反转后的链表的头节点
其实输入都是一样的,输入一个链表的头节点
①方法一:最简单的思路,取出值,再装入新的链表里
数组切片,但是需要额外的空间存储链表
时O(n) 空O(n)
class Solution:
def ReverseList(self , head: ListNode) -> ListNode:
# write code here
stack = [] #把链表逆序存入一个数组里(从题 6学来)
while head:
stack.append(head.val)
head = head.next
stack = stack[::-1] #逆序数组
#学会怎么去新建一个结点
node = ListNode(0) #定义一个结点,给它填入值0,这个结点当作伪头结点
p = node # p是指向这个结点的指针
for num in stack: #意思是num从前往后取一遍stack里的值
p.next = ListNode(num) #往后链接新的结点,填入stack的值
p = p.next
return node.next #输出真正开始表达含义的头结点,node.next才能取出真正的值
②方法二:在1的基础上简化一下,把列表想象成一个栈,把切片操作改成列表的pop操作
class Solution:
def ReverseList(self , head: ListNode) -> ListNode:
# write code here
res = []
while head:
res.append(head.val)
head = head.next
#注意,这里就不需要逆序操作了,等着下面的pop即可
node = ListNode(0)
p = node
while res:#当res列表不为空的时候
p.next = ListNode(res.pop()) #注意这里pop函数要加()的
p = p.next
return node.next
注意:
Ⅰ 把列表名设置成stack老报错,改成别的就正常了,嗯,注意不要设置成特殊指代单词
Ⅱ res.pop() 默认pop尾部的那个
③方法三:双指针
时O(n) 空O(1)
class Solution:
def ReverseList(self , head: ListNode) -> ListNode:
# write code here
cur = head #定义一个指针,和head所指向的位置一样,即头结点
pre = None #定义一个指针,指向空,即None,理解为Null
while cur: #直到cur==None就退出
# 从左往后看去设计,不是从右往左看,要不然全乱套了
tmp = cur.next #设置一个指针,记录cur的后继节点,要不然会丢失
cur.next = pre # cur所在结点的箭头指向pre
#注意第一次写成了 cur = pre,错误,这样是循环不起来的,cur只能代表指针,不代表结点情况
#注意指针指向结点然后进行操作是为了改变结点之间的联系,而不是指针单方面更改位置
pre = cur #pre指针更改位置,指向cur所指的结点
cur = tmp #cur指针更改位置,指向tmp所指的结点,往后移
return pre #输出新的头结点