链表基本知识:
链表是由节点组成的,这个节点有值和指针组成,指针指向下一个节点。链表的地址可以不是连续的。链表在增加和删除节点的时候是比较方便的,但是查找的时候相对麻烦。链表的头结点表示链表的第一个节点,尾节点的指针指向null。
链表有几种常用类型:单链表、双链表和循环链表,双链表有两个指针分别指向前后节点,可以进行双向查询,循环链表的尾节点指向头结点。
203.移除链表元素
之前的时候做过,加一个虚拟头结点,便于返回修改过后的链表,先写一个不加虚拟节点的代码,在删除头结点时候要单独处理,同时应该是while处理而不是if,因为删除第一个头结点之后的节点仍然可能是等于val 的
# 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]:
if head== None:
return head
while head and head.val==val:
head = head.next
cur = head
while cur and cur.next:
if cur.next.val ==val:
cur.next = cur.next.next
else:
cur = cur.next
return head
为了让算法在处理删除头节点和非头节点时候的方式是类似的,我们设置一个虚拟的头结点
class Solution:
def removeElements(self, head: Optional[ListNode], val: int) -> Optional[ListNode]:
virtual_head = ListNode(next = head)
if head== None:
return head
cur = virtual_head
while cur and cur.next:
if cur.next.val ==val:
cur.next = cur.next.next
else:
cur = cur.next
return virtual_head.next
707. 设计链表
class Listnode:
def __init__(self,val=0,next = None):
self.val = val
self.next = next
class MyLinkedList:
def __init__(self):
self.virtual_node = Listnode()
def get(self, index: int) -> int:
i = 0
cur = self.virtual_node
while cur.next:
if index == i:
return cur.next.val
else:
i+=1
cur = cur.next
return -1
def addAtHead(self, val: int) -> None:
new_node = Listnode(val)
new_node.next = self.virtual_node.next
self.virtual_node.next = new_node
return self.virtual_node.next
def addAtTail(self, val: int) -> None:
cur = self.virtual_node
new_node = Listnode(val,next = None)
while cur.next!=None:
cur = cur.next
cur.next = new_node
return self.virtual_node.next
def addAtIndex(self, index: int, val: int) -> None:
cur = self.virtual_node
l = 0
while cur.next:
l+=1
cur = cur.next
if l == index:
self.addAtTail(val)
elif l< index:
return self.virtual_node.next
elif l > index:
new_node = Listnode(val)
cur = self.virtual_node
i=0
while cur.next:
if i==index:
new_node.next=cur.next
cur.next = new_node
break
else:
i+=1
cur = cur.next
return self.virtual_node.next
def deleteAtIndex(self, index: int) -> None:
cur = self.virtual_node
l = 0
while cur.next:
l+=1
cur = cur.next
if l< index:
return self.virtual_node.next
elif l >= index:
cur = self.virtual_node
i=0
while cur.next:
if i==index:
cur.next = cur.next.next
break
else:
i+=1
cur = cur.next
return self.virtual_node.next
# 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)
看了解析,可以把元素数量作为类的一个属性,在增删过程中进行修改,这样就免去了很多求链表长度的问题
206. 反转链表
给定一个链表,需要进行反转,那么我们需要定义一个先前节点指针、一个当前节点指针,并用一个临时节点指针存储下一个要反转的节点
# 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
if head==None or head.next == None:
return head
cur = head
while cur.next:
tmp = cur.next
cur.next=pre
pre = cur
cur = tmp
cur.next=pre
pre = cur
head = cur
return head
自己代码虽然通过了但是写的还是繁杂,后续得好好想想怎么才能写出漂亮代码
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
cur = head
pre = None
while cur:
temp = cur.next # 保存一下 cur的下一个节点,因为接下来要改变cur->next
cur.next = pre #反转
#更新pre、cur指针
pre = cur
cur = temp
return pre