删除链表类的题目不难,全是套路,刷过就很简单
目录
删除链表结点套路总结:
- 虚拟新建虚拟头结点dummy
- dummy->next = head;
- 新建领先结点pre = dummy;因为我们不操作dummy和head
- 对pre进行常规操作即可
注意:
- 注意要新建一个头结点,称为dummyhead
- 新建结点,不能直接在原来的结点上操作!
- 删除下一个结点的语句是 cur->next = cur->next->nex
-
一定要定义指针指向原来的结点操作,否则不管怎样操作原来的结点都是不变的啊!
-
注意判断的时候,不能写成dummy->val的陷阱中,这样会出现最后一个结点无法删除!
LeetCode203.移除链表元素
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
if(head==NULL)
return NULL;
ListNode* dummy = new ListNode(-1);//虚拟头结点
dummy->next = head;//连接
ListNode* pre = dummy;//前置结点,领先一步
while(pre->next){
if(pre->next->val==val)
pre->next = pre->next->next;
else
pre = pre->next;
}
return dummy->next;//返回虚拟头结点
}
};
LeetCode面试题18.删除链表的节点
套上面的套路就可以,其实我还有一个地方没有想明白……
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* deleteNode(ListNode* head, int val) {
ListNode* dummy = new ListNode(0);
dummy->next = head;
if(head->val==val)//如果删除的值位于头部
return head->next;//其实我没有想懂这种情况为什么要单独领出来判断
while(dummy->next->val!=val){//不能写成dummy->val的陷阱中,这样会出现最后一个结点无法删除
dummy = dummy->next;
}
dummy->next = dummy->next->next;
return head;
}
};
LeetCode237.删除链表中的结点
题目一开始没读懂,看了评论区才明白,这道题还是有点鸡贼……
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
void deleteNode(ListNode* node) {
node->val = node->next->val;
node->next = node->next->next;
}
};
或者一行代码:
*node = *(node->next);
LeetCode83.删除排序链表中的重复元素
这里因为是有序的,所以重复元素肯定是挨在一起的,不想下一题要用set,所以这里处理起来就很简单
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head){
ListNode* cur=head;
while(cur&&cur->next){
if(cur->next->val!=cur->val)
cur = cur->next;
else//是重复
cur->next = cur->next->next;
}
return head;
}
};
LeetCode82.删除排序链表中的重复元素II
一定要注意定义dummy和pre结点的重要性!——这是链表题的常规套路!
pre可以解决单向链表中无法指向前结点的问题,dummy用于解决定义一个整体链表的头结点的问题
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
//思路:遍历链表,pre用来指向不重复节点
ListNode* deleteDuplicates(ListNode* head) {
if(!head||!head->next)return head;
ListNode *dummy=new ListNode(-1);
dummy->next=head;
ListNode *pre=dummy;
while(head&&head->next){
if(head->val!=head->next->val){//head与head->next节点值不相等,pre指向head,也就是指向不重复值
pre=head;
head=head->next;
}
else{
//head为重复值子链表的最后一个节点,比如1->1->1->2的最后一个1
while(head&&head->next&&head->val==head->next->val){
head=head->next;
}
//pre连接重复值子链表的之后第一个节点
pre->next=head->next;
head=head->next;
}
}
return dummy->next;
}
};
面试题02.01.移除重复节点
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* removeDuplicateNodes(ListNode* head) {
ListNode* cur = new ListNode(-1);//注意不能赋值为0元素,因为后面可能会出现0元素
cur->next = head;
set<int> s;
while(cur&&cur->next){
if(s.find(cur->next->val)==s.end()&&cur->next->val!=cur->val){//不是重复
s.insert(cur->val);
cur = cur->next;
}else{//是重复
cur->next = cur->next->next;
}
}
return head;
}
};