Leetcode 203.移除链表元素,707.设计链表,206.反转链表
Leetcode 203
题目:
给你一个链表的头节点 head 和一个整数val ,请你删除链表中所有满足Node.val == val的节点,并返回新的头节点 。
示例 1:
输入:head = [1,2,6,3,4,5,6], val = 6
输出:[1,2,3,4,5]
示例 2:
输入:head = [], val = 1
输出:[]
示例 3:
输入:head = [7,7,7,7], val = 7
输出:[]
实现方法:
- 不带头指针的方法
- 带头指针的方法
代码实现:
链表结构定义:
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]:
# 没有头结点版本
# 如果链表的元素都是一样的,那么连续删除
while head != None and head.val == val: # 为什么加个while 假如链表的元素都是一样的
head = head.next
cur = head
while cur != None and cur.next != None:
# 这里的cur != None 统计的是当链表仅有一个元素的时候,防止cur.next 是NoneType
# cur != None:是因为接下来要操作cur.next
# cur.next != None: 是因为接下来要取出来cur.next的val
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]:
# 有头结点版本
# 首先要创建虚拟头结点
dummy_head = ListNode(next=head)
# 不能直接循环虚拟头结点,而是定义当前循环节点
current = dummy_head
while current.next != None:
if current.next.val == val:
current.next = current.next.next
else:
current = current.next
return dummy_head.next # 不能直接返回头结点,可能得情况是当前头结点被删除了
复杂度:
时间复杂度:
O
(
n
)
O(n)
O(n),因为要循环遍历整个列表
空间复杂度:
O
(
1
)
O(1)
O(1)
Leetcode 707
题目
你可以选择使用单链表或者双链表,设计并实现自己的链表。
单链表中的节点应该具备两个属性:val 和 next 。val 是当前节点的值,next 是指向下一个节点的指针/引用。
如果是双向链表,则还需要属性 prev 以指示链表中的上一个节点。假设链表中的所有节点下标从 0 开始。
实现 MyLinkedList 类:
MyLinkedList() 初始化 MyLinkedList 对象。
int get(int index) 获取链表中下标为 index 的节点的值。如果下标无效,则返回 -1 。
void addAtHead(int val) 将一个值为 val 的节点插入到链表中第一个元素之前。在插入完成后,新节点会成为链表的第一个节点。
void addAtTail(int val) 将一个值为 val 的节点追加到链表中作为链表的最后一个元素。
void addAtIndex(int index, int val) 将一个值为 val 的节点插入到链表中下标为 index 的节点之前。如果 index 等于链表的长度,那么该节点会被追加到链表的末尾。如果 index 比长度更大,该节点将 不会插入 到链表中。
void deleteAtIndex(int index) 如果下标有效,则删除链表中下标为 index 的节点。
示例:
输入
[“MyLinkedList”, “addAtHead”, “addAtTail”, “addAtIndex”, “get”, “deleteAtIndex”, “get”]
[[], [1], [3], [1, 2], [1], [1], [1]]
输出
[null, null, null, null, 2, null, 3]
解释
MyLinkedList myLinkedList = new MyLinkedList();
myLinkedList.addAtHead(1);
myLinkedList.addAtTail(3);
myLinkedList.addAtIndex(1, 2); // 链表变为 1->2->3
myLinkedList.get(1); // 返回 2
myLinkedList.deleteAtIndex(1); // 现在,链表变为 1->3
myLinkedList.get(1); // 返回 3
单链表定义
class ListNode:
def __init__(self, val=0, next=None) -> None:
self.val = val
self.next = next
代码实现(这里仅列出但列表法)
class MyLinkedList:
def __init__(self) -> None:
self.dummy_head = ListNode()
self.size = 0
def get(self, index: int) -> int:
if index < 0 or index >= self.size: # 这里为什么是 >=, 如果是等于则会越界
return -1
current = self.dummy_head.next
for i in range(index):
current = current.next
return current.val
def addAtHead(self, val: int) -> None:
self.dummy_head.next = ListNode(val, self.dummy_head.next)
self.size += 1
def addAtTail(self, val: int) -> None:
current = self.dummy_head
while current.next:
current = current.next
current.next = ListNode(val=val)
self.size += 1
def addAtIndex(self, index: int, val: int) -> None:
if index < 0 or index > self.size: # 这里为什么是大于,如果是等于index,就在最后一个位置插入钙元素即可
return
current = self.dummy_head
for i in range(index):
current = current.next
current.next = ListNode(val, current.next)
self.size += 1
def deleteAtIndex(self, index: int) -> None:
if index < 0 or index >= self.size: # 这里为什么是>=, 如果是等于,表示删除最后一个没有在范围内的元素
return
current = self.dummy_head
for i in range(index):
current = current.next
current.next = current.next.next
self.size -= 1
myLinkedList = MyLinkedList()
myLinkedList.addAtHead(1)
myLinkedList.addAtTail(3)
myLinkedList.addAtIndex(1, 2)
myLinkedList.get(1) # 返回 2
myLinkedList.deleteAtIndex(1) # 现在,链表变为 1->3
myLinkedList.get(1)
Leetcode 206
题目
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
示例1:
输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]
示例2:
输入:head = [1,2]
输出:[2,1]
示例 3:
输入:head = []
输出:[]
实现方法:
- 双指针法
- 递归法
代码实现:
链表结构:
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
双指针法:
class Solution:
def reverseList(self, head):
# 利用双指针法
current = head
pre = None
while current:
temp = current.next # 暂存当前节点
current.next = pre
# 先移动pre,后移动current;否则容易造成指针指向问题
pre = current
current = temp
return pre
递归法:
class Solution:
# 这里的递归写法按照双指针法写即可
def reverseList(self, head):
# 递归写法
return self.reverse(head, None)
def reverse(self, cur, pre): # 递归要有个初始化
if cur == None:
return pre
temp = cur.next
cur.next = pre
return self.reverse(temp, cur)
复杂度:
时间复杂度:
O
(
n
)
O(n)
O(n),因为要循环遍历整个列表
空间复杂度:
O
(
1
)
O(1)
O(1)