算法记录Day 3 | 链表part01
LeetCode 203-移除链表元素
题目描述:给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。
输入: head = [1,2,6,3,4,5,6], val = 6
输出: [1,2,3,4,5]
题解
class Solution {
public:
ListNode *removeElements(ListNode *head, int val) {
ListNode *dummyHead = new ListNode();
dummyHead->next = head;
ListNode *prev = dummyHead;
ListNode *cur = head;
while (cur != nullptr) {
if (cur->val == val) {
ListNode *next = cur->next;
prev->next = next;
cur = next;
} else {
cur = cur->next;
prev = prev->next;
}
}
return dummyHead->next;
}
};
解题思路
通常要对链表进行操作,构建一个虚拟头结点是非常有必要的。因为虚拟头结点可以作为前结点prev,它的下一个指针的位置就是head。这题可以用到双指针,方便对链表结点进行删除。
LeetCode 707-设计链表
题目描述:实现 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]
题解
class MyLinkedList {
private:
ListNode *dummyHead;
int size;
public:
MyLinkedList() {
dummyHead = new ListNode();
size = 0;
}
~MyLinkedList() { freeMemoryLinkedList(dummyHead); }
void freeMemoryLinkedList(ListNode *head) {
ListNode *node = head;
while (node != nullptr) {
ListNode *tmp = node;
node = node->next;
delete tmp;
}
head = nullptr;
}
int get(int index) {
if (index > size - 1 || index < 0) {
return -1;
}
ListNode *cur = dummyHead->next;
while (index > 0) {
index--;
cur = cur->next;
}
return cur->val;
}
void addAtHead(int val) {
ListNode *node = new ListNode(val);
ListNode *next = dummyHead->next;
dummyHead->next = node;
node->next = next;
size++;
}
void addAtTail(int val) {
ListNode *node = new ListNode(val);
ListNode *cur = dummyHead;
while (cur->next != nullptr) {
cur = cur->next;
}
cur->next = node;
size++;
}
void addAtIndex(int index, int val) {
ListNode *pre;
pre = dummyHead;
if (index == size) {
addAtTail(val);
return;
} else if (index <= 0) {
addAtHead(val);
return;
} else if (index > size) {
return;
}
for (int i = 0; i < index; i++) {
pre = pre->next;
}
ListNode *node = new ListNode(val);
ListNode *next = pre->next;
pre->next = node;
node->next = next;
size++;
}
void deleteAtIndex(int index) {
if (index > size - 1 || index < 0) {
return;
}
ListNode *pre = dummyHead;
for (int i = 0; i < index; i++) {
pre = pre->next;
}
ListNode *next = pre->next;
pre->next = pre->next->next;
size--;
}
void printLinkedList() {
ListNode *h = dummyHead->next;
while (h != nullptr) {
cout << h->val << " ";
h = h->next;
}
}
};
解题思路
该题需要注意的地方是添加和删除指定元素的index是否合法。使用虚拟头节点可以帮助更轻松掌握对边界情况的控制,避免空指针的访问。维护一个size变量可以判断index是否合法。
LeetCode 206-反转链表
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
输入: head = [1,2,3,4,5]
输出: [5,4,3,2,1]
题解
class Solution {
public:
ListNode *reverseList(ListNode *head) {
if (head == nullptr || head->next == nullptr) {
return head;
}
ListNode *last = reverseList(head->next);
head->next->next = head;
head->next = nullptr;
return last;
}
};
解题思路
经典老题了,递归反转。直接一步走到底,此时last指向最后一个元素,head指向倒数第二个元素,只要不断修改指针的方向,并且将last元素返回,最后一个元素就变成了第一个元素。