移除链表元素
- 题目
- 函数原型
- 边界判断
- 算法设计:哨兵
- 算法设计:递归
题目
删除链表中等于给定值
示例:
输入: 1->2->6->3->4->5->6, val = 6
输出: 1->2->3->4->5
函数原型
C
的函数原型:
struct ListNode* removeElements(struct ListNode* head, int val){
}
边界判断
struct ListNode* removeElements(struct ListNode* head, int val){
}
算法设计:哨兵
思路:好的结构设计,可以简化算法。按照常规的删除方法,释放很多元素都适用,唯独删除第一个元素,需要特殊处理。更好的方法,是采用哨兵实现通用化。
如果删除的节点是中间的节点,则问题似乎非常简单:
- 选择要删除节点的前一个结点
- 将
的
设置为要删除结点的
当要删除的一个或多个节点位于链表的头部时,事情会变得复杂。
可以通过哨兵节点去解决它,哨兵节点广泛应用于树和链表中,如伪头、伪尾、标记等,它们是纯功能的,通常不保存任何数据,其主要目的是使链表标准化,如使链表永不为空、永不无头、简化插入和删除。
在这里哨兵节点将被用于伪头。
typedef struct ListNode Node;
struct ListNode* removeElements(struct ListNode* head, int val){
// 创建哨兵结点
Node* sentinel = malloc( sizeof(Node) );
sentinel->next = head; // 哨兵 -> 头指针
Node* cur = sentinel;
while( cur->next != NULL ){
if( cur->next->val == val ){ // 找到了,就删除结点
Node* del_node = cur->next;
cur->next = del_node->next;
free(del_node), del_node = NULL;
}else
cur = cur->next;
}
Node* ans = sentinel->next;
free(sentinel), sentinel = NULL;
return ans;
}
- 时间复杂度:
- 空间复杂度:
算法设计:递归
思路:链表的增、删、改、查都可以用递归实现,这个也是。
struct ListNode* removeElements(struct ListNode* head, int val){
if( head == NULL )
return NULL;
//2、递去:直到到达链表尾部才开始删除重复元素
head->next = removeElements(head->next, val);
//3、递归式:相等就是删除head,不相等就不用删除
return head->val==val ? head->next : head;
}
- 时间复杂度:
- 空间复杂度: