这一部分自刷的时候跳过了(因为据说华子不考),只看了数据结构里面的理论部分。现在补上
链表理论:
定义链表
class ListNode:
def __init__(self, val, next=None):
self.val = val
self.next = next
一个值、一个next指针指向下一个节点的存储位置。
next等于None的时候表示链表结束----->常用判断链表是否结束的语句
while current.next: ##当前节点的next指针不为空
调用该节点的值和指针的方法:
目前的节点名叫current,eg:current.val(当前节点存储值) current.next(当前节点存储的指向的下一个节点的指针)
可以重复连续使用:eg:current.next.val(当前节点的下一个节点的值)current.next.next(当前节点下下个位置存储的指针)
在链表中新加入时,构造语法该为:
节点位置 = LinkNode(值,要指向的下个节点位置)
203.移除链表元素
主要是不太熟悉列表理论。next太多了要绕晕,冷静思考!!!
# 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]:
xunihead = ListNode(next=head)#定义一个虚拟头节点,指针下一个是目标链表
cur = xunihead
while cur.next:
if cur.next.val == val:#由于设了个虚拟头结点,所以从cur.next(原定头节点)开始找
cur.next = cur.next.next#找到了目标值,则直接把下一个要读取的位置跳到下下个节点,把cur.next跳过去
else:
cur = cur.next#没有找到目标值,于是正常向下读
return xunihead.next#去掉虚拟头节点
209.设计链表
class LinkNode:
def __init__(self,val=0,next=None):#构造一个链表,
self.val = val
self.next = next
class MyLinkedList:#链表的五种操作
def __init__(self):#初始化变量的作用。意思是在调用这个类的时候,都要先运行这个。这里定义的变量,后面的函数都可以直接调用
self.dummy_head = LinkNode()#加入虚拟头节点
self.size = 0#定义一个size变量,并初始化赋值为0
def get(self, index: int) -> int:
if index<0 or index>=self.size:#注意违规条件,也有等号,index的范围应该是0到size-1
return -1
# cur = self.dummy_head.next
# for i in range(index):
# cur = cur.next
# return cur.val
i=0
cur = self.dummy_head#对cur赋初始值,掉因init中定义的变量
while i < index:#i最大值是index-1,i=0的时候cur才等于原head,因此index-1才到index前一位
cur = cur.next
i += 1
return cur.next.val
def addAtHead(self, val: int) -> None:
self.dummy_head.next = ListNode(val, self.dummy_head.next)#构造链表的方式,ListNode(值,指向的位置)
self.size += 1#别忘记size要加1
def addAtTail(self, val: int) -> None:
cur = self.dummy_head
while cur.next:#链表无法直接找到最后一个节点的位置,因此需要从第一个节点开始遍历
cur = cur.next
cur.next = LinkNode(val,None)
self.size+=1
def addAtIndex(self, index: int, val: int) -> None:
if index < 0 or index > self.size:#非法操作,则不做任何操作,直接结束
return
cur = self.dummy_head
for i in range(index):
cur = cur.next
cur.next = LinkNode(val,cur.next)
self.size += 1
def deleteAtIndex(self, index: int) -> None:
if index < 0 or index >= self.size:#非法操作,则不做任何操作,直接结束,注意有等号
return
cur = self.dummy_head
for i in range(index):#找到index的前一个节点,i=0的时候指向原head的第一个节点,因此最后一次操作刚好指向index-1的节点
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)
链表几个要注意的点
1、链表无法直接到达指定index节点位置,需要从头开始遍历。而且链表的输入输出都只需要头节点,其他的节点是可以从头节点开始往后查的,已经捆绑了!
2、链表index的范围,和列表相似都是0到size-1,在判定违法输入时要特别注意判断条件index是<size还是<=size,注意思考有没有等号
3、使用虚拟头节点的话,如果想要找到index的位置,要注意遍历循环结束时,是停在了index-1的位置还是index的位置。根据不同的需要设定遍历循环的起始位置!
4、如果需要多个列表应该调用多次class LinkNode,eg:
class ListNode:
def __init__(self, val=0, next=None):#构造时,括号里要写好初始值,别忘了!!
self.val = val
self.next = next
class MyLinkedList:
def __init__(self):
self.head = None
def add_at_head(self, val):
new_node = ListNode(val)
new_node.next = self.head
self.head = new_node
# 创建两个链表对象
list1 = MyLinkedList()
list2 = MyLinkedList()
# 向链表中添加节点
list1.add_at_head(1)
list1.add_at_head(2)
list1.add_at_head(3)
5、还有新认识到的类!
函数def __init__(self): 初始化变量的作用。意思是在调用这个类的时候,都要先运行这个。这里定义的变量,后面的函数都可以直接调用。但是记得都要带self!!!例如在init中定义了self.dummy_head,那么之后每次引用时都要带self.,即self.dummy_head,而非是dummy_head
206.反转链表
双指针法:
把cur的指针指向pre,然后cur和pre指针都向前移动
##双指针
# 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]:
cur = head#初始化两个指针
pre = None
while cur:
temp = cur.next#因为等下cur.next要指向pre(cur是没变的)
cur.next = pre#把cur的指针(cur.next)指向前一个(pre)
cur = temp #更新输入输出变量,指针位置往前移动
pre = cur
return pre#只需要输出头节点,后面的节点式存储在头节点中的
递归法没太看懂……
感谢GPT今天把递归补上了。递归的核心思想就是函数的返回量 是调用这个函数本身,直至满足终止条件,属于是while的函数写法了。把这部分单独写成一个函数的话,应该是能让主函数更加简洁?
# 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]:
return self.reverse(head,None)
def reverse(self, cur: ListNode, pre: ListNode) -> ListNode:
if cur == None:#链表到达最后,此时的pre就是头节点
return pre
temp = cur.next
cur.next = pre #把指针指向前一个节点
return self.reverse(temp,cur)