Remove all elements from a linked list of integers that have value val.
Example
Given: 1 --> 2 --> 6 --> 3 --> 4 --> 5 --> 6, val = 6
Return: 1 --> 2 --> 3 --> 4 --> 5
MySolution
1 仿照上一篇文章,用非val值的节点的值来覆盖值等于val的节点的值。思路比较简单,但一些边边角角的情况要处理。最后还要释放不用了的节点。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* removeElements(struct ListNode* head, int val) {
// 空链表
if(!head)
{
return NULL;
}
// 链表非空
struct ListNode *index1 = head;
struct ListNode *index2 = head;
struct ListNode *previous = NULL;
while(index2 != NULL)
{
index1->val = index2->val;
if(index2->val != val)
{
previous = index1;
index1 = index1->next;
}
index2 = index2->next;
}
if(!previous) // 链表全部被删除
{
index2 = index1->next;
while(index2) // 释放后面的节点
{
free(index1);
index1 = index2;
index2 = index2->next;
}
free(index1);
return NULL;
}
else // 链表部分节点被删除或没有任何节点被删除
{
previous->next = NULL;
if(index1) // 防止出现没有删除任何节点,index1和index2同时为NULL的情况
{
index2 = index1->next;
while(index2) // 释放后面的节点
{
free(index1);
index1 = index2;
index2 = index2->next;
}
free(index1);
}
return head;
}
}
效率还可以,只是不断地赋值有些繁琐。而且一旦节点的数据变多,这种方式极不方便,相应的 时间开销也会加大。
2. 遍历链表,删除值等于给定val的节点。要注意的是,题目给的链表是没有真正的头结点(即不存储数据,只用来当做头部使用)的。当然可以在函数中构造一个,但嫌麻烦,就不构造了,单独列出几种特殊情况进行判断。
代码如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* removeElements(struct ListNode* head, int val) {
if(!head)
{
return NULL;
}
if(!head->next)
{
if(head->val == val)
{
return NULL;
}
else
{
return head;
}
}
else
{
struct ListNode *previous = head;
struct ListNode *current = head->next;
// 从第二个节点开始检查,是否有val值
while(current)
{
if(current->val == val)
{
previous->next = current->next;
free(current);
}
else
{
previous = current;
}
current = previous->next;
}
// 检查头结点
if(head->val == val)
{
current = head;
head = head->next;
free(current);
}
return head;
}
}
先排除空链表和只有一个元素的链表,剩余的情况中,从链表的第二个元素中开始遍历,释放所有要删除的节点,并将其余节点连起来。最后再判断一下第一个元素是否要删除即可。
实践证明,这种方法效率最高。