您现在的位置是:首页 >学无止境 >代码随想录算法训练营第三天 | 203.移除链表元素、 707.设计链表、206.反转链表网站首页学无止境
代码随想录算法训练营第三天 | 203.移除链表元素、 707.设计链表、206.反转链表
简介代码随想录算法训练营第三天 | 203.移除链表元素、 707.设计链表、206.反转链表
一、203.移除链表元素
1.使用原链表进行移除节点操作
代码如下:
/**
* 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 != NULL && head->val == val){
ListNode* tmp = head;//(1)
head = head->next;
delete tmp;//(2)
//(1)、(2)两句的作用是C++释放空间
}
ListNode* cur = head;
while (cur != NULL && cur->next != NULL){//cur不能为空,因为接下来要操作cur->next,cur为空的话会出现空指针报错
//cur->next也不能为空,因为要去cur->next的值和val进行对比,如果cur->next为空,有属于操作空指针了
if (cur->next->val == val){
ListNode* tmp = cur->next;//因为比较的是cur->next的值,因此tmp要设置为cur->next。tmp可以理解为待删除的值
cur->next = cur->next->next;
delete tmp;
}
else{
cur = cur->next;
}
}
return head;//因为定义了一个临时指针cur,是使用cur来进行遍历的,head还是指向一开始操作的链表
}
};
注意:
1、如果直接用头节点head遍历链表,那么这个头节点指向的值是不断变化的,最后就没有办法返回原先链表的头节点了。所以要定义一个临时的指针cur来遍历链表
2、要删的是cur的next,要删一个元素的话,一定要知道上一个元素的指针是什么,所以上一个只能是cur。删cur的next的话,才能让cur的指针指向下一个节点的下一个节点
3、使用虚拟头节点时,为什么返回dummyHead->next而不是head,因为head可能已经被删了,dummyHead的下一个(dummyHead->next)才是新链表的头节点
2.设置一个虚拟头节点进行移除节点操作
代码如下:
/**
* 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* dummyHead = new ListNode(0); //new操作符的使用要再看看
dummyHead->next = head;
ListNode* cur = dummyHead;
while(cur->next != NULL){//注意!!要操作的对象是cur->next,所以要判断cur->next这个指针是否为空,不能操作空指针
if (cur->next->val == val){
ListNode* tmp = cur->next;//注意!!要删除的是cur->next,不是cur!
cur->next = cur->next->next;
delete tmp;
}
else{
cur = cur->next;
}
}
head = dummyHead->next;
delete dummyHead;
return head;//新链表的头节点为dummy->next,不能直接返回dummy->next,因为C++需要手动清理内存
}
};
二、707.移除链表元素
class MyLinkedList {
public:
//定义链表节点结构体
struct LinkedNode {
int val;
LinkedNode* Next;
LinkedNode(int val):val(val), Next(nullptr){}//链表节点的构造函数
//LinkedNode是链表节点的类名
//int val是节点的值,是一个整数
//构造函数初始化了该节点的值val作为传入的参数val,初始化了指针next为空指针
};
MyLinkedList() {
_dummyHead = new LinkedNode(0);
_size = 0;
}
int get(int index) {
if (index > (_size - 1) || index < 0) {
return -1;
}
LinkedNode* cur = _dummyHead->Next;
while (index--){
cur = cur->Next;
}
return cur->val;
}
void addAtHead(int val) {
LinkedNode* newNode = new LinkedNode(val);//创建一个新结点 //new操作符的语法还不太懂
newNode->Next = _dummyHead->Next;//不写=head的原因:能够获取head的地址,在_dummyHead->next中
_dummyHead->Next = newNode;
//这里有一个先后顺序,要先把新节点和头节点链接,再把虚拟头节点和新节点链接;否则,先将虚拟头节点和新节点链接后,无法获取头节点的地址(头节点的地址存在虚拟头节点的next指针中)
_size++;
}
void addAtTail(int val) {
LinkedNode* newNode = new LinkedNode(val);
LinkedNode* cur = _dummyHead;
//当前遍历指针一定要指向尾部节点,要找尾部节点
while (cur->Next != nullptr){//cur->next=NULL时即尾部节点,不为空就一直遍历
cur = cur->Next;
}
cur->Next = newNode;//newnode在定义的时候默认next=NIULL
_size++;
}
void addAtIndex(int index, int val) {
if (index > _size) {//如果index大于链表长度,返回空
return ;
}
LinkedNode* newNode = new LinkedNode(val);
LinkedNode* cur = _dummyHead;
while (index--) {
cur = cur->Next;
}
newNode->Next = cur->Next;//cur已经遍历到需要插入的位置
cur->Next = newNode;
_size++;
}
void deleteAtIndex(int index) {//要删第n个节点,一定需要知道前一个节点的next,因为要让它指向n后的节点
if (index >= _size || index < 0){//为什么上面一个>,这个是>=?
return ;
}
LinkedNode* cur = _dummyHead;
while (index--) {
cur = cur->Next;
}
LinkedNode* tmp = cur->Next;
cur->Next = cur->Next->Next;
delete tmp;
_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);
*/
三 、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* reverse(ListNode* pre, ListNode* cur) {
if (cur == NULL) return pre;
struct ListNode* tmp = cur->next;
cur->next = pre;
return reverse(cur, tmp);
}
ListNode* reverseList(ListNode* head) {
return reverse(NULL, head);
}
};
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。