Leetcode 203 移除链表元素
-
主要思想
- 常规
-
非头 head 节点
找到要移除节点的前一个节点,指向要移除节点的下一个节点 -
移除头部节点
Head 节点:将head 移到下一节点,head = head.next
-
- 改进
- 虚拟头节点方法
- Why:上述删除有两种情况,这里想统一这两种情况的代码
- 虚拟头节点方法
- 常规
-
操作
- Method1:直接删除
- 先判断要删的元素是否为head 节点
- 判断条件:头节点是否为空 & 头节点所指向的数值 = target 要删除的数值
- 操作:头节点指向下一个,head = head -> next
- Method1:直接删除
df
2. 删除非头节点的指针
-- 伪代码
while (head != null) & (head -> val == target): // 持续移除头节点
head = head.next
- 代码
- 两步法
class Solution(object):
def removeElements(self, head, val):
"""
:type head: ListNode
:type val: int
:rtype: ListNode
"""
while (head != None) and (head.val == val):
head = head.next
# other nodes
cur = head
while (cur != None) and (cur.next != None):
if cur.next.val == val:
cur.next = cur.next.next
else:
cur = cur.next
return head
- trick点
# 1. 第一个 while 的使用
## 错误写法:会导致超时;这种情况下,可以直接在条件部分就进行判断
while (head != None) and (head.next != None):
if head.val == val:
head = head.next # 会导致超时
# 2. cur.next 和 cur.next.next
## 错误写法:会导致最后1个6没有处理,因为cur.next.next == None
cur = head
while (cur.next != None) and (cur.next.next != None): # 当cur = 5时,因为 cur.next.next is null, 所以没有处理最后一个6,就直接结束了while 循环
if cur.next.val == val:
cur.next = cur.next.next
else:
cur = cur.next
return head
- 虚拟头节点
class Solution(object):
def removeElements(self, head, val):
"""
:type head: ListNode
:type val: int
:rtype: ListNode
"""
dummy_head = ListNode(next = head)
cur = dummy_head
while cur.next != None:
if cur.next.val == val: # 补充.val,之前只写了cur.next
cur.next = cur.next.next
else:
cur = cur.next
return dummy_head.next
- tricky点
- cur.next 加上.val
Leetcode 707 设计链表
- 题目链接
- 代码
# 单链表
class MyLinkedList:
def __init__(self):
# self.val = val
# self.next = None
self._head = ListNode(0) # 虚拟头部节点, val = 0
self._count = 0 # 初始状态 count = 0
def get(self, index: int) -> int:
if 0 <= index < self._count: # self._count = index + 1
cur = self._head.next
while index > 0 :
cur = cur.next
index -= 1
return cur.val
else:
return -1
def addAtHead(self, val: int) -> None:
self._count += 1
add_node = ListNode(val)
add_node.next = self._head.next
self._head.next = add_node
# def addAtHead(self, val: int) -> None:
# """
# Add a node of value val before the first element of the linked list. After the insertion, the new node will be the first node of the linked list.
# """
# self.addAtIndex(0, val)
def addAtTail(self, val: int) -> None:
self._count += 1
cur = self._head
while cur.next != None:
cur = cur.next
add_node = ListNode(val)
cur.next = add_node
# def addAtTail(self, val: int) -> None:
# """
# Append a node of value val to the last element of the linked list.
# """
# self.addAtIndex(self._count, val)
def addAtIndex(self, index: int, val: int) -> None:
if index < 0 :
index = 0
elif index > self._count:
return
else:
self._count += 1
add_node = ListNode(val)
# prev, cur = self._head, self._head.next index = 0 的话需要另行考虑
prev, cur = None, self._head
# 寻找第 index 个节点
for _ in range(index + 1):
prev, cur = cur, cur.next # 错误: prev, cur = prev.next, cur.next; prev = None
# add node
add_node.next = cur
prev.next = add_node
# def addAtIndex(self, index: int, val: int) -> None:
# """
# Add a node of value val before the index-th node in the linked list. If index equals to the length of linked list, the node will be appended to the end of linked list. If index is greater than the length, the node will not be inserted.
# """
# if index < 0:
# index = 0
# elif index > self._count:
# return
# # 计数累加
# self._count += 1
# add_node = ListNode(val)
# prev_node, current_node = None, self._head
# for _ in range(index + 1):
# prev_node, current_node = current_node, current_node.next
# else:
# prev_node.next, add_node.next = add_node, current_node
def deleteAtIndex(self, index: int) -> None:
if 0 <= index < self._count:
self._count -= 1
prev, cur = None, self._head
# 寻找第 index 个节点
for _ in range(index + 1):
prev, cur = cur, cur.next # 错误: prev, cur = prev.next, cur.next; prev = None
# delete node
prev.next = cur.next
else:
return -1
# def deleteAtIndex(self, index: int) -> None:
# """
# Delete the index-th node in the linked list, if the index is valid.
# """
# if 0 <= index < self._count:
# # 计数-1
# self._count -= 1
# prev_node, current_node = None, self._head
# for _ in range(index + 1):
# prev_node, current_node = current_node, current_node.next
# else:
# prev_node.next, current_node.next = current_node.next, None
Leetcode 206 反转链表
- 思想
- raw:定义一个新链表 -> 浪费内存空间
- now:只需要改变链表的next指针的指向,直接将链表反转
- 解法
- 双指针
- General
- 双指针
- cur指针,指向头结点
- 定义一个pre指针,初始化为null,定义在cur前面,以便于反转
- pre 和 cur 指针不断向后移动;每移动一次,改变cur与pre之间的指针方向
- 细节
- pre 初始化为null,因为反转后head指向null
- 遍历结束:pre = 尾节点,cur = None时
- While cur
- 结果:pre称为新链表的头节点
- 赋值
-
临时指针:temp = cur.next;防止指向pre节点时,cur与cur.next没有指针连接
-
反转后,先移动pre,后移动cur
- Pre = cur
- Cur = temp
-
# 双指针
# 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: ListNode) -> ListNode:
cur = head
pre = None
while(cur != None):
temp = cur.next # 保存一下 cur的下一个节点,因为接下来要改变cur->next
cur.next = pre #反转
#更新pre、cur指针
pre = cur
cur = temp
return 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: ListNode) -> ListNode:
def reverse(pre,cur):
if not cur:
return pre
tmp = cur.next
cur.next = pre
return reverse(cur,tmp)
return reverse(None,head)