题目:leetcode 203 移除链表元素
题意:给定链表的头节点和目标值,删除链表中与目标值相等的元素,返回新的头节点(因为头节点可能就是要删除的元素)
思路1 不使用虚拟头节点,直接在原链表节点上操作
这样出现的问题是:删除头节点和删除其他节点的方式不同,需要 单独写删除头节点的操作
while(head != nullptr && head->val == val) { head = head->next; }
注意:是while 而不是 if ,如一组数据 [1,1,1,1,1,1] ,目标值 val = 1,那么我们要持续移除头节点,所以要用 whlle
还有一点是:删除节点只是让他指向了下一个位置,并没有真正删除,还需要内存释放,在C++中需要这样写,就是定义一个临时节点,通过它来间接删除(其他语言有内存回收机制,所以不需要写)
while (head != nullptr && head->val == val) { ListNode* tmp = head; head = head->next; delete tmp; }
接下来是其他节点的删除:要注意的是 定义的 cur 节点是指向head 而不是 head->next,因为要删除元素需要知道它的上一个节点,如[1,4,2,3] val = 4, 我们要删除4,如果把cur 指向的是4 ,我们不知道它的上一个节点是谁,没有记录。而如果把cur 指向 head ,那么 4 就是cur->next,我们删除4 就只需要 让 cur->next = cur->next->next;
我当时的误区:误认为它的前一个节点就是head,不会变化
如果不是目标值,那么cur就会变化,它的上一个节点就不知道是谁了
完整代码如下:
/**
* 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* removeElements(ListNode* head, int val) {
while(head != nullptr && head->val == val) {
head = head->next;
}
ListNode* cur = head;
while(cur != nullptr && cur->next != nullptr) {
if (cur->next->val == val) {
cur->next = cur->next->next;
} else {
cur = cur->next;
}
}
return head;
}
};
思路2: 采用虚拟头结点的方式,让 删除节点的方式可以统一
ListNode* dummy_head = new ListNode(0); dummy_head->next = head; ListNode* cur = dummy_head;
注意 :头结点的指针不能变得,最后我们要返回头节点,如果用头节点去遍历,头节点的指针就变来变去,所以需要定义一个临时指针cur
这里 同样注意是 cur = dummy_head 而不是 dummy_head->next
/**
* 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* removeElements(ListNode* head, int val) {
ListNode* dummy_head = new ListNode(0);
dummy_head->next = head;
ListNode* cur = dummy_head;
while(cur->next != nullptr) {
if(cur->next->val == val) {
cur->next = cur->next->next;
} else {
cur = cur->next;
}
}
return dummy_head->next;
}
};
题目:leetcode 707 设计链表
题意: 本题考查链表的基本操作,比较锻炼代码能力,注意这里的index 是从 0 开始的
class MyLinkedList {
public:
struct LinkedNode {
int val;
LinkedNode* next;
LinkedNode(int val):val(val), next(nullptr){};
};
MyLinkedList() {
_dummyhead = new LinkedNode(0);
_size = 0;
}
int get(int index) {
if (index < 0 || (index > (_size - 1))) {
return -1;
}
LinkedNode* cur = _dummyhead->next;
while (index) {
cur = cur->next;
index--;
}
return cur->val;
}
void addAtHead(int val) {
LinkedNode* newnode = new LinkedNode(val);
newnode->next = _dummyhead->next;
_dummyhead->next = newnode;
_size++;
}
void addAtTail(int val) {
LinkedNode* newnode = new LinkedNode(val);
LinkedNode* cur = _dummyhead;
while(cur->next != nullptr) {
cur = cur->next;
}
cur->next =newnode;
_size++;
}
void addAtIndex(int index, int val) {
if (index < 0 || index > _size) {
return;
}
LinkedNode* newnode = new LinkedNode(val);
LinkedNode* cur = _dummyhead;
while(index) {
cur = cur->next;
index--;
}
newnode->next = cur->next;
cur->next = newnode;
_size++;
}
void deleteAtIndex(int index) {
if(index < 0 || index > _size - 1) {
return;
}
LinkedNode* cur = _dummyhead;
while (index) {
cur = cur->next;
index--;
}
cur->next = cur->next->next;
_size--;
}
private:
int _size;
LinkedNode* _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);
*/
题目:leetcode 206 反转链表
思路:双指针算法
定义两个指针,一个pre,一个cur,cur初始化为 head,让它指向head,由于反转之后原先的head指向了null,所以pre初始化为null
循环终止条件:当cur指针指向null的时候,pre指针就指向了尾节点,此时pre就是反转后的头节点直接返回就可以
注意:这里需要定义一个临时指针来存储cur->next,因为cur->next要指向pre,即cur->next = pre,此时cur->next值就改变了,而我们的cur接着移动到下一个节点即cur->next,所以需要临时定义一个temp来存cur->next,确保cur移动到下一个节点的值没有变
还有一点:是先让pre = cur ,然后让 cur = temp, 否则cur 的值已经变化了,pre就没有正确的指向cur的位置
/**
* 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* pre = nullptr;
ListNode* cur = head;
while(cur != nullptr) {
ListNode* temp = cur->next;
cur->next = pre;
pre = cur;
cur = temp;
}
return pre;
}
};