了解链表
打字的时候不注意,发现写了节点和结点两个表述,将就看吧
什么是链表,链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域一个是指针域(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针的意思)。
链表的入口节点称为链表的头结点也就是head。
链表的定义
python
# 定义链表的节点类
class ListNode:
"""
链表节点类,每个节点包含:
- val: 节点存储的值
- next: 指向下一个节点的指针(默认None)
"""
def __init__(self, val=0, next=None):
self.val = val # 节点值
self.next = next # 指向下一个节点的引用
链表的操作
删除节点

添加节点

与数组的区别
数组是在内存中是连续分布的,但是链表在内存中可不是连续分布的。
链表是通过指针域的指针链接在内存中各个节点。
性能对比

203.移除链表元素
题目链接203. 移除链表元素 - 力扣(LeetCode)
思路
删除这个节点,需要他的前一个指向他的后一个,但如果需要删除的节点是头节点,那他的前一个节点又是什么?可以用head=head->next,这样我们需要区分头节点和非头节点去进行删除操作。还有一个方法是设定虚拟头节点,这样不需要区分头结点和非头结点进行删除操作。
其实设定虚拟头结点的方法在很多链表类的题目里面都有用到

伪代码
python
dummyhead=new()
dummyhead->next=head//把这个虚拟头结点放在head的前面
cur=dummyhead//临时指针遍历链表,删cur->next
while(cur->next!=null):
if(cur->next==target):
cur->next=cur->next->next
else:
cur=cur->next
return dummyhead->next//新链表的头结点
写题
报错1

修改:
python
while(cur.next):
错误2

修改:
是删除的结果有问题,看删除逻辑
发现我这一行写错了
python
if(cur.next.val==val):
cur.next=cur.next.next
之前写的是cur.val==val
提交成功

python
# 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]:
dummy=ListNode(0)
dummy.next=head
cur=dummy
while(cur.next):
if(cur.next.val==val):
cur.next=cur.next.next
else:
cur=cur.next
return dummy.next
707.设计链表

看到这里一半的力气都没了,怎么要写这么多函数
思路
设定虚拟头结点
另外需要注意,第0个结点是头结点
伪代码
python
cur=dummyhead->next
//获取第n个节点的值
while(n):
cur=cur->next
n--
return cur->val//如果n=0不进入whle循环,直接返回头结点的值,所以上面给cur赋值的时候也是给的头结点
//头部插入节点
newnode=Newnode()
newnode->next=head
dummyhead->next=newnode
//注意顺序如果先dummyhead->next=newnode,后面head就获取不到了,所以是先给head
//尾部插入节点
//找尾部
cur=dummyhead
newnode=Newnode()
while(cur.next):
cur=cur.next
cur.next=newnode
//第n个节点前插入节点
//需要cur指向第n-1个节点,然后cur.next指向第n个节点
cur=dummyhead
newnode=Newnode()
while(n):
cur=cur->nxt
n--
newnode->next=cur.next
cur.next=newnode
//删除第n个节点
cur=dummyhead
//需要cur指向第n-1个节点,然后cur.next指向第n个节点
while(n):
cur=cur->nxt
n--
cur->next=cur->next->next
写题
python
class ListNode:
def __init__(self,val=0,next=None):
self.val=val
self.next=next
class MyLinkedList:
def __init__(self):
self.dummy=ListNode(0)
self.size=0
这部分看了题解,因为自己写的时候大脑一片空白
后面对链表操作是自己写的
错误1

测试用例部分通过,提交的时候出了问题,我再看看。有一半通过一半没通过??
addAtIndex 方法的边界条件错误
-
官方 / 常规逻辑中,
addAtIndex(index, val)允许index == self.size(此时等价于在尾部添加),但写的条件是index>=self.size就返回 -1,直接限制了 "在尾部添加" 的合法场景。 -
该方法的返回值错误:题目要求这些操作(add/delete)是
None类型,你却返回了-1(只有get方法需要返回值)。
deleteAtIndex方法的返回值错误
- 和上面同理,
deleteAtIndex不需要返回值,但写了return -1,不符合规范。
提交成功
就是边界条件,特别是那个size,还有cur到哪个地方开始操作

python
class ListNode:
def __init__(self,val=0,next=None):
self.val=val
self.next=next
class MyLinkedList:
def __init__(self):
self.dummy=ListNode(0)
self.size=0
def get(self, index: int) -> int:
if index<0 or index>=self.size:
return -1
cur=self.dummy.next
while(index):
cur=cur.next
index-=1
return cur.val
def addAtHead(self, val: int) -> None:
newnode=ListNode(val)
newnode.next=self.dummy.next
self.dummy.next=newnode
self.size+=1
def addAtTail(self, val: int) -> None:
cur=self.dummy
newnode=ListNode(val)
while(cur.next):
cur=cur.next
cur.next=newnode
self.size+=1
def addAtIndex(self, index: int, val: int) -> None:
if index<0 or index>self.size:
return
cur=self.dummy
newnode=ListNode(val)
while(index):
cur=cur.next
index-=1
newnode.next=cur.next
cur.next=newnode
self.size+=1
def deleteAtIndex(self, index: int) -> None:
if index<0 or index>=self.size:
return
cur=self.dummy
while(index):
cur=cur.next
index-=1
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)
再练习练习
下午又写了一遍,最重要还是搞清楚从哪个地方找,是对cur做处理还是cur的next做处理
获取当前index的值,cur就要到index位置
在index位置添加,就在cur(index的前一个位置)和cur.next(index位置)之间加入
在index位置删除,就在cur(index的前一个位置),cur.next(index位置)
另外就是index是否可以包括self.size
206.反转链表
思路
绕,转圈
伪代码
python
cur=head
pre=null//cur的前一个节点
//什么时候遍历结束,cur一直往后面走,走,到最后一个元素还是需要反转,但是最后一个元素后面的null到这里就可以结束了
while(cur):
temp=cur->next//需要一个临时指针把cur的下一个位置保存
cur->next=pre
pre=cur
cur=temp
return pre

2,3是把pre和cur往后面移的意思
写题

中间有一次返回是空,return cur
应该是return pre
python
# 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]:
pre=None
cur=head
while(cur):
temp=cur.next
cur.next=pre
pre=cur
cur=temp
return pre