对于初学链表的学者来学,链表是比较困难的,这部分对指针结构体的要求比较高。我们通过练习是掌握知识的重要途经
203. 移除链表元素 - 力扣(LeetCode)
我们在数组中去除某元素是遍历一遍数组,如果某位置是要去除的元素,就将后面的元素挪过来覆盖了,我们要去除的元素。这样的效率是不是特别的慢,假如每个元素都是要去除的,时间复杂度为O(N^2)
在链表中,我们知道数据是存储在不连续的空间的,一个数据内有下一个元素的地址,我们移除链表的数据只要改变前一个数据内存储的指向我们要移除的数据的地址.
我们还可以将不是val的值全部存储到一个新的结构体指针内,然后将新开辟的结构体指针返回即可
代码写到这样整体逻辑是没有问题的,但是细节我们处理到位所以导致我们无法运行出来。看我们的报错
不能通过的用例是[1,2,6,3,4,5,6]
什么原因导致的
因为可能全部都是要删除的元素,所以我们的tail也可能为空指针
当tail不为空的时候我们tail的next
struct ListNode* removeElements(struct ListNode* head, int val)
{
struct ListNode* newnode =NULL;
struct ListNode* tail =NULL;
struct ListNode* cur =head;
while(cur)
{
if(cur->val!=val)
{
if(tail==NULL)
{
tail=newnode=cur;
}
else
{
tail->next=cur;
tail=tail->next;
}
cur=cur->next;
}
else
{
struct ListNode* ret=cur->next;
free(cur);
cur=ret;
}
}
if(tail!=NULL)
tail->next=NULL;
return newnode;
}
这个题也可以通过双指针来进行操作
struct ListNode* removeElements(struct ListNode* head, int val)
{
struct ListNode* prev=NULL;
struct ListNode* cur=head;
while(cur)
{
if(cur->val!=val)
{
prev=cur;
cur=cur->next;
}
else
{
if(prev==NULL)
{
head=cur->next;
free(cur);
cur=head;
}
else
{
prev->next=cur->next;
free(cur);
cur=prev->next;
}
}
}
return head;
}
双指针解决问题的时候大家要注意头删的时候操作和后面的删除操作是不相同的,头删后,我们头的位置发生变化