相关链接
视频讲解:移除链表元素视频讲解
视频讲解:帮你把链表操作学个通透!LeetCode:707.设计链表_哔哩哔哩_bilibili
视频讲解:帮你拿下反转链表 | LeetCode:206.反转链表 | 双指针法 | 递归法_哔哩哔哩_bilibili
移除链表元素
题目说明:给你一个链表的头节点 head
和一个整数 val
,请你删除链表中所有满足 Node.val == val
的节点,并返回 新的头节点 。
解题思路-原地移除链表的元素
看到题目我想到的就是原地移除链表元素,但在实现过程中忘记考虑不同的情况。若移除的是头结点的元素则需要单独处理,将head指针指向下一个就可以。若移除的元素非头结点,则将该元素的前一个指针指向该元素的后一个位置。
总结
1)由于是单链表,指针应该指向移除元素的前一个位置,便于进行相关操作。
2)养成手动删除内存的习惯。
3)由于力扣已给出链表的定义,以后需要练习定义链表的结构体。
AC代码:
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
while(head!=NULL&&head->val==val)
{
ListNode* tmp=head;
head=head->next;
delete tmp;
}
ListNode* p=head;
while(p!=NULL&&p->next!=NULL)
{
if(p->next->val==val)
{
ListNode* tmp=p->next;
p->next=p->next->next;
delete tmp;
}
else
p=p->next;
}
return head;
}
};
解题思路-使用虚拟结点
使用虚拟头结点便于统一操作,注意需要创建一个新的指针便于删除元素,该指针应指向虚拟头结点,因为若删除元素为真正的头结点,则需要知道该结点的上一个指针。此外最后返回的应该是虚拟头结点的下一个元素,不能返回头指针,因为头指针可能已被删除。
AC代码:
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
ListNode* vhead=new ListNode(0);
vhead->next=head;
ListNode* p=vhead;
while(p->next!=NULL)
{
if(p->next->val==val)
{
ListNode* tmp=p->next;
p->next=p->next->next;
delete tmp;
}
else
p=p->next;
}
return vhead->next;
}
};
设计链表(重点掌握,复盘之后独立写一遍!!!)
遇到的困难
1)结构体定义不熟悉,之后需要复习这块的基础知识。
2)大致思路清楚,但是小bug不断,对index的判断不到位。
AC代码:
class MyLinkedList {
public:
struct LinkedNode{
int val;
LinkedNode* next;
LinkedNode(int val):val(val),next(nullptr){}
};
MyLinkedList() {
_vhead=new LinkedNode(0);
_size=0;
}
int get(int index) {
if(index<0||index>(_size-1))
return -1;
LinkedNode* p=_vhead->next;
while(index)
{
p=p->next;
index--;
}
return p->val;
}
void addAtHead(int val) {
LinkedNode* p=new LinkedNode(val);
p->next=_vhead->next;
_vhead->next=p;
_size++;
}
void addAtTail(int val) {
LinkedNode* p=new LinkedNode(val);
LinkedNode* q=_vhead;
while(q->next!=NULL)
{
q=q->next;
}
q->next=p;
_size++;
}
void addAtIndex(int index, int val) {
if(index>_size)
return;
if(index<0)
index=0;
LinkedNode* k=new LinkedNode(val);
LinkedNode* p=_vhead;
while(index)
{
p=p->next;
index--;
}
k->next=p->next;
p->next=k;
_size++;
}
void deleteAtIndex(int index) {
if(index>=_size||index<0)
{
return ;
}
LinkedNode* p=_vhead;
while(index)
{
p=p->next;
index--;
}
LinkedNode* tmp=p->next;
p->next=p->next->next;
delete tmp;
tmp=nullptr;
_size--;
}
private:
int _size;
LinkedNode* _vhead;
};
/**
* 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);
*/
反转链表
遇到的困难
这个题目之前写过几次,但是每次都是半知半解,知道用双指针的解法但是就是写不出来,看了视频讲解,发现最重要的就是要建立一个临时指针,以及三个指针的运行顺序。
AC代码:
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* pre=nullptr;
ListNode* cur=head;
ListNode* tmp;
while(cur!=nullptr)
{
tmp=cur->next;
cur->next=pre;
pre=cur;
cur=tmp;
}
return pre;
}
};
总结
数据结构当初学的就不是太好,正好带着补充一些知识,链表画图易于理解,重要的是知道链表的存储结构以及一些循环终止条件的判断。