【Leetcode刷题随笔】203移除链表元素

1.题目描述

题意:删除链表中等于给定值 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 输出:[]
原题链接:203移除链表元素

2.解题思路

由于链表本身的性质,移除链表的某个节点a,只需要将前一个节点的next指针指向a的下一个节点即可(C或C++需要手动从内存中删除被移除的这个节点)。此时有一个需要注意的点,就是如果头结点需要被移除怎么操作?此时有两种方法:

  • 直接将头结点后移
  • 使用虚拟头结点

对于第一种方法,因为链表的其他节点都是通过前一个节点来移除当前节点,而头结点没有前一个节点,你可以直接将head指向下一个节点,但就和其他节点的处理规则不统一,需要另外的代码去专门处理头结点,对于复杂一点的问题比较麻烦。

如果想用统一的逻辑处理所有节点,可以用第二种方法,设置一个虚拟头结点dummy,使其next指向真实的头结点,此时若想删除真实头结点就可以将虚拟头结点的next指向真实头结点的next,实现逻辑统一。最后在代码返回的时候返回dummy->next即可。这种方式在链表操作中很常用。

3. C语言实现

3.1 方法一

struct ListNode* removeElements(struct ListNode* head, int val){
    struct ListNode* temp; //定义别名
    // 当头结点存在并且头结点的值等于val时删除并释放内存
    while(head && head->val == val) {
        temp = head;
        // 将新的头结点设置为head->next并删除原来的头结点
        head = head->next;
        free(temp);
    }
	
	//通过cur来遍历链表,初始指向head
    struct ListNode *cur = head;
    // 当cur存在并且cur->next存在时
    // 此解法需要判断cur存在因为cur指向head。若head本身为NULL或者原链表中元素都为val的话,cur也会为NULL
    while(cur && (temp = cur->next)) {
        // 若cur->next的值等于val
        if(temp->val == val) {
            // 将cur->next设置为cur->next->next并删除cur->next
            cur->next = temp->next;
            free(temp);
        }
        // 若cur->next不等于val,则将cur后移一位
        else
            cur = cur->next;
    }

    // 返回头结点
    return head;
}

3.2 方法二

struct ListNode* removeElements(struct ListNode* head, int val) {
    typedef struct ListNode ListNode;
    //创建一个虚拟头结点dummy并为其分配内存,将其next指向原本的头结点
    ListNode *dummy;
    dummy = (ListNode*)malloc(sizeof(ListNode));
    dummy->next = head;
	
	//通过cur来遍历链表,cur初始指向dummy
    ListNode *cur = dummy;

	//使用 while 循环遍历链表,条件是当前节点的下一个节点不为空(即未到达链表末尾)。
    while(cur->next != NULL){
    	//如果当前节点的下一个节点的值等于 val,则需要删除该节点并释放内存。
        if(cur->next->val == val){
            ListNode *temp = cur->next;
            cur->next = cur->next->next;
            free(temp);
        }else{
        	//如果当前节点的下一个节点的值不等于 val,则将 cur 移动到下一个节点,继续遍历。
            cur = cur->next;
        }
    }
    //遍历结束后,将 head 指向虚拟头节点的下一个节点(即新的链表头节点),释放掉虚拟头结点。
    head = dummy->next;
    free(dummy);
    return head;
}

你可能感兴趣的:(leetcode链表篇,leetcode,链表,算法)