1. Remove Linked List Elements(leetcode 203)
题目:给定一个链表头节点 head 和一个整数 val,删除链表中所有满足 Node.val == val 的节点,并返回新的头节点
最直观的想法就是遍历链表,遇到节点值等于val的节点就删除它,遇到不等于val的节点则保留。需要注意处理头节点可能被删除的情况。
比较基本的操作,考察基本的数据结构理解和代码操作能力。
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
while (head && head->val == val) {
head = head->next;
}
if (!head) return head;
ListNode* n = head;
while (n->next) {
if (n->next->val == val) {
n->next = n->next->next;
}
else {
n = n->next;
}
}
delete n;
return head;
}
};
复杂度分析
- 时间复杂度: O(n),其中 n 是链表的长度。需要遍历链表一次。
- 空间复杂度: O(1)
2. Reverse Linked List(leetcode 206)
题目:给你单链表的头节点 head,请你反转链表,并返回反转后的链表。
- 最初想到的方法是,遍历链表,把每个节点的值存到一个数组里,再从数组从后往前构建一个新链表。这需要O(n)的额外空间。
- 更好的方法是原地反转。用三个指针pre,cur,nxt分别表示前一个节点,当前节点和后一个节点,边遍历边反转节点的指向。
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if (!head) return head;
if (head && !head->next) return head;
vector<int> v;
ListNode* ptr = head;
while (ptr) {
v.push_back(ptr->val);
ptr = ptr->next;
}
int size = v.size() - 1;
ListNode* newHead = new ListNode(v[size]);
ListNode* cur = newHead;
for (int i = size - 1 ; i >= 0; i--) {
cur->next = new ListNode(v[i]);
cur = cur->next;
}
return newHead;
}
};
Better approach:
class Solution2 {
public:
ListNode* reverseList(ListNode* head) {
ListNode* prev = nullptr;
ListNode* curr = head;
while (curr) {
ListNode* temp = curr->next;
curr->next = prev;
prev = curr;
curr = temp;
}
return prev;
}
};
3. Design Linked List(Leetcode707)
题目:设计链表的实现。
反思总结:
通过这道题的练习,复习了单链表的基本操作。但在代码实现过程中,还是有些小细节需要注意,比如在插入和删除操作时,需要先找到对应位置的前一个节点。另外在各种操作前,需要判断链表是否为空以及索引是否有效。
总的来说,对链表的操作还不够熟练,还需要多加练习。接下来打算继续练习一些链表相关的题目,如链表的反转、合并等,以加深对链表的理解和应用。同时还要注意培养编码的耐心,养成仔细分析问题的习惯。
class LinkedNode {
public:
LinkedNode* next;
int val;
LinkedNode (int val , LinkedNode* next) : val(val), next(next) {}
LinkedNode (int val) : val (val) , next(nullptr){}
};
class MyLinkedList {
private:
LinkedNode* head;
public:
//constructor
MyLinkedList(int size, LinkedNode* head) : head(head) {}
MyLinkedList() : head(nullptr) {}
int get(int index) {
if (index < 0 || !head) return -1;//invalid index
if (index == 0 && head) return head->val;
LinkedNode* temp = head;
for (int i = 0; i < index; i++) {
temp = temp->next;
if (!temp) return -1;
}
return temp->val;
}
void addAtHead(int val) {
LinkedNode* newhead = new LinkedNode(val);
if (!head) {
head = newhead;
}
else {
newhead->next = head;
head = newhead;
}
}
void addAtTail(int val) {
LinkedNode* tail = new LinkedNode(val);
if (!head) {
head = tail;
return;
}
LinkedNode* ptr = head;
while (ptr->next) {
ptr = ptr->next;
}
ptr->next = tail;
}
void addAtIndex(int index, int val) {
if (index < 0) return;
if (index == 0) {
addAtHead(val);
return;
}
int count = 0;
LinkedNode* temp = head;
while (count < index - 1 && temp)//loop need to be stoped at index -1 then perform insertion
{
temp = temp->next;
count++;
}
if (!temp) return;
else {
LinkedNode* ptr = temp->next;
temp->next = new LinkedNode(val, ptr);
}
}
void deleteAtIndex(int index) {
if (index < 0 || !head) return;
if (index == 0) {
LinkedNode* temp = head;
head = head->next;
return;
}
int count = 0;
LinkedNode* ptr = head;
while (count < index - 1 && ptr) {
ptr = ptr->next;
count++;
}
if (!ptr || !ptr->next) return;
else {
LinkedNode* temp = ptr->next->next;
ptr->next = temp;
}
}
};