栏目分类:
子分类:
返回
文库吧用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
文库吧 > IT > 软件开发 > 后端开发 > C/C++/C#

【手撕OJ题】——203. 移除链表元素(四种思路:C实现)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【手撕OJ题】——203. 移除链表元素(四种思路:C实现)

目录
  •  题目:
  • ⌛ 总体思路:
    •  方法①-无哨兵结点的遍历
    •  方法②-有哨兵结点的遍历
    •  方法③-尾插新链表
    •  方法④-递归
  •  附:单链表调试数据

 题目:

 203. 移除链表元素【难度:简单】
给你一个链表的头节点 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
⌛ 总体思路:

遍历链表,一一比较结点的val是否为要删除的。若为要删除的结点:先释放掉此结点,再将此结点的上一结点链接到此结点的下一结点

 方法①-无哨兵结点的遍历

 思路:
定义一个cur:表示指向要删的元素结点;
定义一个prev:表示要删的元素的前面的结点;
区分头删和非头删的情况,头删则修改头指针的指向。
先让prev的next指向cur的next;再释放cur;同时,cur要继续迭代往前走,找是否还有要删除的元素,此时让cur指向prev的next即可;
如果链表为空,直接返回空指针;

struct ListNode* removeElements(struct ListNode* head, int val)
{
    struct ListNode* cur = head,*prev = NULL;
    while(cur)  //遍历到要删除的结点
    {
        if(cur->val == val)
        {
            // 1.头删  2.非头删
            if(cur == head)     //头删单独处理
            {
                head = head->next;  //修改头指针的指向,不在指向头结点
                free(cur);
                cur = head;
            }
            else
            {
                prev->next = cur->next;
                free(cur);
                cur = prev->next;
            }
        }
        else
        {
            prev = cur;
            cur = cur->next;
        }
    }
    // 当退出循环表示cur到尾结点 空链表则不进入循环直接返回
    return head;
}


这里传参我们注意到,修改了头指针好像并没有用二级指针传参诶,但又成功了,为什么呢❓

struct ListNode* removeElements(struct ListNode* head, int val)
{
	......
	return head;
}

原因就在这里,返回了新的头指针

 方法②-有哨兵结点的遍历

 思路:相比于没有哨兵结点的迭代,有哨兵结点的遍历可以不区分头删与非头删。

struct ListNode* removeElements(struct ListNode* head, int val)
{
    struct ListNode* cur = head;
    struct ListNode* guard = (struct ListNode*)malloc(sizeof(struct ListNode));
    struct ListNode* tail = guard;

    while(cur)
    {
        if(cur->val != val)
        {
            tail->next = cur;
            tail = tail->next;

            cur = cur->next;
        }
        else
        {
            struct ListNode* del = cur;
            cur = cur->next;
            free(del);
        }
    }

    // 最后节点是val,就会出现此问题
    if(tail)
        tail->next = NULL;

    head = guard->next;
    free(guard);

    return head;
}


⌛ 小结:

替代我们之前实现的二级指针的方法:

  • 返回新的链表头
  • 设计为带哨兵位的
 方法③-尾插新链表

 思路:把不是val的结点尾插到新链表,然后返回新链表

struct ListNode* removeElements(struct ListNode* head, int val)
{
    struct ListNode* cur = head;
    struct ListNode* newhead = NULL, *tail = NULL;
    while(cur)
    {
        if(cur->val != val)
        {
            if(tail == NULL)
            {
                newhead = tail = cur;
            }
            else
            {
                tail->next = cur;
                tail = tail->next;
            }

            cur = cur->next;
        }
        else
        {
            struct ListNode* del = cur;
            cur = cur->next;
            free(del);
        }
    }

    // 最后节点是val,就会出现此问题
    if(tail)
        tail->next = NULL;

    return newhead;
}

 方法④-递归

 思路:要删除val,返回头结点;
那么我们就递归删除head->next即可得到一个新的结点newNode;

这个结点就是删除完后的结点;用head->next链接newNode;
然后再判断head头结点是否要删除的值:不是就直接返回head,是的就直接返回head->next(即newNode结点)

struct ListNode* removeElements(struct ListNode* head, int val) 
{
        if(!head ) 
            return NULL;
        //要删除链表中的结点:也就是删除head->next的结点
        struct ListNode* newNode = removeElements(head->next,val);
        head->next = newNode;   //头结点连接删好后的链表
        return head->val == val ? head->next : head;    //判断头节点的值是否和要删的val相同
}

 附:单链表调试数据

做题一定要画图+调试,备一份数据以后方便在VS里面调试

int main()
{
	struct ListNode* n1 = malloc(sizeof(struct ListNode));
	assert(n1);
	struct ListNode* n2 = malloc(sizeof(struct ListNode));
	assert(n2);
	struct ListNode* n3 = malloc(sizeof(struct ListNode));
	assert(n3);
	struct ListNode* n4 = malloc(sizeof(struct ListNode));
	assert(n4);
	struct ListNode* n5 = malloc(sizeof(struct ListNode));
	assert(n5);
	struct ListNode* n6 = malloc(sizeof(struct ListNode));
	assert(n6);
	struct ListNode* n7 = malloc(sizeof(struct ListNode));
	assert(n7);

	n1->next = n2;
	n2->next = n3;
	n3->next = n4;
	n4->next = n5;
	n5->next = n6;
	n6->next = n7;
	n7->next = NULL;

	n1->val = 1;
	n2->val = 2;
	n3->val = 6;
	n4->val = 3;
	n5->val = 4;
	n6->val = 5;
	n7->val = 6;

	struct ListNode* head = removeElements(n1, 6);

	return 0;
}
转载请注明:文章转载自 www.wk8.com.cn
本文地址:https://www.wk8.com.cn/it/1038473.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 wk8.com.cn

ICP备案号:晋ICP备2021003244-6号