结点删除三部曲

针对于结点删除,我先介绍剑指offer 18 删除链表的节点。

题目:

给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。
返回删除后的链表的头节点。

示例:

输入: head = [4,5,1,9], val = 5
输出: [4,1,9]
解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9.

使用上面哑结点的技巧,结合模拟法的思考,很自然地得到下面的代码:


/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* deleteNode(ListNode* head, int val) {
        ListNode* dummyHead = new ListNode(0); // 删除节点需要制造一个新的头结点安排在现有的头结点之前,这是常用手段
        dummyHead->next = head;
        ListNode* flag = dummyHead;
        while (dummyHead->next != nullptr) {
            if (dummyHead->next->val == val) { 
                dummyHead->next = dummyHead->next->next;
                break;
            }
            dummyHead = dummyHead->next;
        }
        return flag->next;
    }
};
这样,我们解决了今天的第一道题目。

第二道题目是力扣83 删除排序链表中的重复元素。我建议先写这题再写今天的每日一题,因为是一个系列的题目,且循序渐进。

题目:

给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次。

示例:

输入: 1->1->2
输出: 1->2

解题思路还是很清晰的,跳过重复元素即可,下面是代码:


/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) { // 链表  本题根据题目要求,跳过重复值的节点即可
        ListNode* cur = head;
        while (cur != nullptr && cur->next != nullptr) {
            if (cur->val == cur->next->val) {
                cur->next = cur->next->next;
            }
            else {
                cur = cur->next;
            }
        }
        return head;
    }
};
细心的朋友会发现,这题为什么没有用哑结点呀?
因为这题只需要删除重复元素就好,不用把一个元素斩草除根。所以不用设置哑结点。

所以很轻松地,又解决一道题。

最后是今天的题目。和上面的力扣83做比较,发现今天的题目需要把重复的元素斩草除根地删去。显然我们要使用哑结点了。

下面是代码:


/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        if (head == nullptr) return head;  // 特判
        ListNode* dummy = new ListNode(0, head); // 设置哑结点
        ListNode* cur = dummy; 
        while (cur->next && cur->next->next) { // 当cur->next与cur->next->next都存在的时候
            if (cur->next->val == cur->next->next->val) { // 如果遇到后面两个连续数值相等,那么记录下这个数值
                int x = cur->next->val;
                while (cur->next && cur->next->val == x) { // 将重复元素删除,这里设置while循环,可以删去多个重复元素
                    cur->next = cur->next->next; // 在删除元素的过程中,一定要好好理解cur->next的变化,这里很容易出错
                    // 建议大家在草稿纸上进行推演,你会发现很简单
                }
            }
            else {
                cur = cur->next; // 如果没发现重复元素,那么正常推进
            }
        }
        return dummy->next; // 返回头结点
    }
};
 

至此,解决了第三道题目。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值