203.移除链表元素
解析:
该题给出的是一个不带头节点的单链表,因此若想对val值的节点删除需要处理两种情况:
- 从起始位置开始,一直连续的需要删除
- 起始节点不需要删除
本算法是一个直接在原链表上删除的算法,是单向的遍历与删除,不涉及回溯,且单次删除操作为O(1),只需常数个中间变量,因此总题时间复杂度为O(n),空间复杂度为O(1)。
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
while(head != NULL && head->val == val){ //处理从头节点开始不断需要删除的情况
ListNode* q = head;
head = head->next;
delete q;
}
ListNode* cur = head;
ListNode* pre = head; //此时 head必不满足删除条件 pre、cur从head开始
while(cur != NULL){
if(cur->val == val){
pre->next = cur->next; //满足删除条件时,pre不动,但pre->next指向内容要略过当前的cur
ListNode* q = cur;
cur = cur->next;
delete q;
}
else{
pre = cur; //无需删除则更新pre及cur的位置,pre要先于cur更新
cur = cur->next;
}
}
return head;
}
};
我们同样可以降此链表构造成一个带头节点的链表,这样删除操作便能得到统一(即便head位置就需要删除,我们同样可以降删除操作简化成一类,因为我们有一个dummy_head能够把这个底兜住)
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
ListNode* dummy_head = new ListNode(0);
dummy_head->next = head; //新的头节点
ListNode* cur = head;
ListNode* pre = dummy_head;
while(cur){
if(cur->val == val){
pre->next = cur->next;
ListNode* p = cur;
cur = cur->next;
delete p;
}
else{
pre = cur;
cur = cur->next;
}
}
head = dummy_head->next;
delete dummy_head;
return head;
}
};
707.设计链表
解析:
链表基本操作,不再赘述。
class MyLinkedList {
public:
struct LinkNode{
int val;
LinkNode* next;
LinkNode(int val):val(val), next(nullptr){}
};
MyLinkedList() {
_dummyHead = new LinkNode(0);
_size = 0;
}
int get(int index) {
if(index > (_size - 1) || index < 0){
return -1;
}
LinkNode* cur = _dummyHead->next;
while(index--){
cur = cur->next;
}
return cur->val;
}
void addAtHead(int val) {
LinkNode* p = new LinkNode(val);
p->next = _dummyHead->next;
_dummyHead->next = p;
_size++;
}
void addAtTail(int val) {
LinkNode* p = new LinkNode(val);
LinkNode* q = _dummyHead;
while(q->next != NULL){
q = q->next;
}
p->next = q->next;
q->next = p;
_size++;
}
void addAtIndex(int index, int val) {
if(index > _size) return;
if(index < 0) index = 0;
LinkNode* newNode = new LinkNode(val);
LinkNode* cur = _dummyHead;
while(index--) {
cur = cur->next;
}
newNode->next = cur->next;
cur->next = newNode;
_size++;
}
void deleteAtIndex(int index) {
if(index > (_size - 1) || index < 0){
return ;
}
LinkNode* cur = _dummyHead;
while(index--) {
cur = cur ->next;
}
LinkNode* tmp = cur->next;
cur->next = cur->next->next;
delete tmp;
_size--;
}
private:
int _size;
LinkNode* _dummyHead;
};
/**
* Your MyLinkedList object will be instantiated and called as such:
* MyLinkedList* obj = new MyLinkedList();
* int param_1 = obj->get(index);
* obj->addAtHead(val);
* obj->addAtTail(val);
* obj->addAtIndex(index,val);
* obj->deleteAtIndex(index);
*/
206.反转链表
解析:
基础题之一,链表反转。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* temp; // 保存cur的下一个节点
ListNode* cur = head;
ListNode* pre = NULL;
while(cur) {
temp = cur->next; // 保存一下 cur的下一个节点,因为接下来要改变cur->next
cur->next = pre; // 翻转操作
// 更新pre 和 cur指针
pre = cur;
cur = temp;
}
return pre;
}
};