LeeCode链表问题(一)
本文中所使用的链表定义如下所示:
# Definition for singly-linked list.
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
// Definition for singly-linked list.
public class ListNode {
int val;
ListNode next;
ListNode() {}
ListNode(int val) { this.val = val; }
ListNode(int val, ListNode next) { this.val = val; this.next = next; }
}
LeeCode 203: 移除链表元素
题目描述:
给你一个链表的头节点
head
和一个整数val
,请你删除链表中所有满足Node.val == val
的节点,并返回新的头节点。
标签: 链表,递归
时间复杂度:O(N)
建立模型:
- 移除非头节点:通过前一节点的next属性指向被移除节点的next节点即
pre.next = cur.next
- 移除头节点:直接将head后移一位即
head = head.next
- 为了统一上面两种操作,创建一个虚拟头节点,其next属性指向head,这样所有节点的移除都被归类为非头节点
- 返回虚拟头节点的next域
代码实现:
# Python3 实现
def removeElement(self, head: ListNode, val: int) -> ListNode:
virtual_head = ListNode(val=0, next=head)
pre, cur = virtual_head, head
while cur is not None:
if cur.val == val:
pre.next = cur.next
else:
pre = cur
cur = cur.next
return virtual_head.next
// Java 实现
public ListNode removeElements(ListNode head, int val) {
ListNode virtualHead = new ListNode(0, head);
ListNode pre = virtualHead;
ListNode cur = head;
while (cur != null) {
if (cur.val == val)
pre.next = cur.next;
else
pre = cur;
cur = cur.next;
}
return virtualHead.next;
}
LeeCode 707: 设计链表
题目描述:
设计链表的实现,可以选择使用单链表或双链表。单链表中的节点应该具有两个属性:
val
和next
。val 是当前节点的值,next 是指向下一个节点的指针/引用。如果要使用双向链表,则还需要一个属性prev
以指示链表中的上一个节点。假设链表中的所有节点都是 0-index 的。
在链表中实现这些功能:
- get(index): 获取链表中第
index
个节点的值。如果索引无效,则返回-1 - addAtHead(val): 在链表的第一个元素之前添加一个值为
val
的节点。插入后,新节点将成为链表的第一个节点 - addAtTail(val): 将值为
val
的节点追加到链表的最后一个元素 - addAtIndex(index, val): 在链表的
index
位置添加值为val
的节点。如果index
的长度等于链表的长度,则将该节点添加到链表的末尾;如果index
大于链表长度,则不会插入节点;如果index
小于0,则在头部插入节点 - deleteAtIndex(index): 如果索引
index
有效,则删除链表中在index
位置的节点
建立模型:
- 考虑使用单链表实现
- 需要初始化头节点和链表长度
- 按功能添加代码
代码实现:
# Python3 实现
class MyLinkedList:
def __init__(self):
self.size = 0
self.head = None
def get(self, index: int) -> int:
if index >= self.size:
return -1
temp = self.head
for _ in range(index):
temp = temp.next
return temp.val
def addAtHead(self, val: int) -> None:
node = ListNode(val, None)
if self.head is None:
self.head = node
else:
temp = self.head
self.head = node
self.head.next = temp
self.size += 1
def addAtTail(self, val: int) -> None:
node = ListNode(val, None)
if self.head is None:
self.head = node
else:
temp = self.head
while temp.next:
temp = temp.next
temp.next = node
self.size += 1
def addAtIndex(self, index: int, val: int) -> None:
if index > self.size:
print("Add: Index out of range!")
return
if index == self.size:
self.addAtTail(val)
elif index <= 0:
self.addAtHead(val)
else:
pre = self.head
for _ in range(index - 1):
pre = pre.next
cur = pre.next
# 插入Node
node = ListNode(val, None)
pre.next = node
node.next = cur
self.size += 1
return
def deleteAtIndex(self, index: int) -> None:
if index < 0 or index >= self.size:
print("Delete: Index out of range!")
return
if index == 0:
self.head = self.head.next
else:
pre = self.head
for _ in range(index - 1):
pre = pre.next
cur = pre.next
# 删除cur节点
pre.next = cur.next
self.size -= 1
return
LeeCode 206: 反转链表
题目描述:
给你单链表的头节点
head
,请你反转链表,并返回反转后的链表。
标签:链表,递归
时间复杂度:O(N)
建立模型:
- 定义两个指针 previous=head,current=head.next
- 将current指针的next节点保存在temp中
- 翻转previous,current的前后关系
- 更新previous,current指向的节点
代码实现:
# Python3 实现
def reverseList(self, head: ListNode) -> ListNode:
# 空链表或只有一个节点的链表翻转还是它自己
if not head or not head.next:
return head
previous, current = head, head.next
previous = None
while current:
temp = current.next
current.next = previous
# 更新 previous, current节点
previous = current
current = temp
return previous
// Java 实现
public ListNode reverseList(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode previous = head;
ListNode current = head.next;
previous.next = null;
while (current != null) {
ListNode temp = current.next;
current.next = previous;
previous = current;
current = temp;
}
return previous;
}
LeeCode 24: 两两交换链表中的节点
题目描述:
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即只能进行节点交换)。
题目解释:
- 若链表节点个数为偶数,则每两个节点交换即(1, 2), (3, 4), ..., (N-1, N)
- 若链表节点个数为奇数,则前N-1个节点每两个交换,最后一个节点不交换即(1, 2), (3, 4), ..., (N-2, N-1), (N)
建立模型:
- 定义两个指针 previous=virtual_head,current=head
- 将要与current交换的节点保存在following中
- 交换两个相邻的节点
- 更新previous,current节点
代码实现:
# Python3 实现
def swapPairs(self, head: ListNode) -> ListNode:
virtual_head = ListNode(0, head)
previous, current = virtual_head, head
while current and current.next:
following = current.next
# 交换两个相邻节点
previous.next = following
current.next = following.next
following.next = current
# 更新previous, current节点
previous = current
current = current.next
return virtual_head.next
// Java 实现
public ListNode swapPairs(ListNode head) {
ListNode virtualHead = new ListNode(0, head);
ListNode previous = virtualHead;
ListNode current = head;
while (current != null && current.next != null) {
ListNode following = current.next;
previous.next = following;
current.next = following.next;
following.next = current;
previous = current;
current = current.next;
}
return virtualHead.next;
}