给你一个链表的头节点 head
和一个整数 val
,请你删除链表中所有满足 Node.val == val
的节点,并返回 新的头节点 。
示例 1:
输入:head = [1,2,6,3,4,5,6], val = 6 输出:[1,2,3,4,5]
示例 2:
输入:head = [], val = 1 输出:[]
示例 3:
输入:head = [7,7,7,7], val = 7 输出:[]
提示:
- 列表中的节点数目在范围
[0, 104]
内 1 <= Node.val <= 50
0 <= val <= 50
【方法一】单指针
第一步:判断特殊情况,链表中第一个元素是要删除的元素,则进行删除第一个节点。
第二步:如果链表为空,则直接返回空链表。
第三步:定义一个指针p,指向第一个元素(也就是本题中的头节点)
第四步:当链表的第二个节点开始不为空的时候,进行判断第二个节点中的元素是否为要删除的元素。如果是,则将p的后继指向p的后继的后继;如果不是,则将p节点向后移动。
第五步:返回删除后的链表。
具体案例分析:
输入:head = [6,1,2,6,3,4,5,6], val = 6 输出:[1,2,3,4,5]
首先第一个节点为要删除的节点,则将head=head->next。(也就是删除第一个6)此时链表为[1,2,6,3,4,5,6]。
定义一个指针p,将p指向head(也就是第一个节点1),此时p->next不为空,则进行判断p的后继节点中的数据是否为6,不是则进行向后遍历,也就是p=p->next;当p指向第2个节点的时候(2),此时p的后继是6,需要将6进行删除,则执行p->next=p->next->next(也就是2后面连接3,将6进行删除),最后继续进行遍历............达到最后的链表[1,2,3,4,5]
C语言具体代码如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* removeElements(struct ListNode* head, int val){
while(head != NULL && head->val == val){
head= head->next;
}
if(head==NULL){
return head;
}
struct ListNode *p=head;
while(p->next != NULL){
if(p->next->val == val){
p->next=p->next->next;
}else{
p=p->next;
}
}
return head;
}
时间复杂度O(n);空间复杂度O(1)
【方法二】双指针
第一步:如果链表为空,则直接返回空链表。
第二步:判断特殊情况,链表中第一个元素是要删除的元素,则进行删除第一个节点。
第三步:定义指针p,q,p指向第一个元素(也就是本题中的头节点),q作为移动指针。
第四步:p不为空时(也就是链表不为空时)。如果p中的数据不为要删除的值,则令q=p(将q指针标记在p这个地方),然后将p=p->next(p进行向后遍历);如果p中的数据为要删的值是,q->next=p->next(将要删除的前一个节点的后继指向要删除节点的后继,也就是删除知定的值),然后将p=p->next(p进行向后遍历)。
第五步:返回删除后的链表。
具体案例分析:
输入:head = [6,1,2,6,3,4,5,6], val = 6 输出:[1,2,3,4,5]
首先第一个节点为要删除的节点,则将head=head->next。(也就是删除第一个6)此时链表为[1,2,6,3,4,5,6]。
定义一个指针p和q,将p指向head(也就是第一个节点1),此时p不等于6,将q指向p(也就是现在p和q都指向1),然后将p向后遍历。
此时p指向2,不用删除,将q指向p(也就是现在p和q都指向2),然后将p向后遍历。
此时p指向6,需要删除,将q(此时q在2这个地方)的后继指向p的后继(也就是2->3),然后将p=p->next(此时p指向3),然后将p继续向后遍历...........
C语言具体代码如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* removeElements(struct ListNode* head, int val){
if(head==NULL){
return head;
}
while(head != NULL && head->val == val){
head= head->next;
}
struct ListNode *p=head;
struct ListNode *q;
while(p != NULL){
if(p->val != val){
q=p;
p=p->next;
}else{
q->next=p->next;
p=p->next;
}
// 上述的两句p=p->next可以写在这个地方
//也就是说,只用写这一句即可,执行效率会更快,分别写在上面两个地方是为了方便理解
}
return head;
}
时间复杂度O(n);空间复杂度O(1)