力扣203. 移除链表元素
# 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]:
dh = ListNode(None) # 建立虚拟头节点
dh.next = head # 作为头节点的前置虚拟结点
cur = dh # 从虚拟结点开始遍历
while cur.next != None: # 循环终止条件,用while而不是if
if cur.next.val == val:
cur.next = cur.next.next
else:
cur = cur.next
return dh.next
力扣707. 设计链表
加强类模块的学习,刚接触链表,定义和初始化不熟练。
class Node:
def __init__(self, x=0):
self.val = x
self.next = None
class MyLinkedList(object):
def __init__(self):
self.head = Node()
self.size = 0 # 设置一个链表长度的属性,便于后续操作,注意每次增和删的时候都要更新
def get(self, index: int) -> int:
if index < 0 or index >= self.size: # 索引出错返回-1,=size时索引越界
return -1
cur = self.head.next
while index: # 不等于0时
index -= 1
cur = cur.next
return cur.val
def addAtHead(self, val: int) -> None:
new_head = Node(val) #定义头结点数据类型
new_head.next = self.head.next # 先链接虚拟结点的下一个,即头结点
self.head.next = new_head # 后将新的头结点链接到虚拟节点后
self.size += 1
def addAtTail(self, val: int) -> None:
new_tail = Node(val)
cur = self.head #从第一个虚拟结点开始遍历
while cur.next:
cur = cur.next
cur.next = new_tail
self.size += 1
def addAtIndex(self, index: int, val: int) -> None:
if index < 0:
self.addAtHead(val)
return
elif index == self.size:
self.addAtTail(val)
return
elif index > self.size:
return
#当在链表中间插入时
insert_node = Node(val)
cur = self.head # 指针位于虚拟结点
while(index):
cur = cur.next
index -= 1
insert_node.next = cur.next # 先链接后面
cur.next = insert_node # 再连接前面
self.size += 1
def deleteAtIndex(self, index: int) -> None:
cur = self.head
if index >= 0 and index < self.size: # index = 0删除头部结点
while index:
index -= 1
cur = cur.next # 注意计入了虚拟结点,index = 0时对应实际链表第二个结点即index = 1
cur.next = cur.next.next
self.size -= 1
力扣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
cur = head
while cur != None:
tem = cur.next # 保留cur的下一个,避免翻转时找不到下一个
cur.next = pre
pre = cur
cur = tem
return pre
总结:
虚拟头结点避免头节点是空
不能直接用头节点作为指针,因为在增减链表操作时头节点可能回改变。
链表增减先更新插入边,后将上一结点与新结点链接,顺序颠倒则可能指向混乱。
反转方法:双指针和递归。为了能在head反转后找到head下一个结点,注意创建head结点的下一结点tem结点(备份)。为了能够将cur的值保留到pre,先移动pre后移动cur