LeetCode:删除排序链表中的重复元素 II(双指针法+递归法)

题目:LeetCode——删除排序链表中的重复元素 II

一、双指针法:

1.添头法:

需要想清楚定义几个指针或节点用于保存,并新建一个节点做头。

class Solution {
public:
    // 共四个指针要用变量存储:
    // 一、返回值的头dummy;
    // 二、删除起始处的上一个节点pre
    // 三、删除起始处p1
    // 四、删除终止处p2

    ListNode* deleteDuplicates(ListNode* head) {
        ListNode* dummy = new ListNode(250, head);  // 虚增的头,解决链表开始即重复的问题
        ListNode* pre = dummy;

        ListNode* p1 = head;
        while (p1 != nullptr) {
            ListNode* p2 = p1 -> next;
            while ((p2 != nullptr) && (p1 -> val == p2 -> val)) {
                p2 = p2 -> next;
            }
            // 至此,p2指向重复节点的后面一个节点
            if (p2 != p1 -> next) {   //有重复
                pre -> next = p2;  // 出现连续需要删除的多段节点时,刷新pre->next
            } else {
                pre = p1;
            }
            p1 = p2;
        }
        return dummy -> next;
    }
};

2.子函数法:

能拆分出一个完整返回下一个非重复节点的功能即可。

class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        ListNode* realHead = brige(head);  // 链表的头,首个非重复节点
        ListNode* hang(realHead);  // 需要挂起,直至找到匹配的节点
        while (hang != nullptr) {
            hang->next = brige(hang->next);
            hang = hang->next;
        }
        return realHead;
    }

private:
    // INPUT: 某链表的head
    // OUTPUT: 返回第一个重复节点后的链表指针或本身
    ListNode* brige(ListNode* head) {
        ListNode* waiter(head);
        ListNode* explorer(nullptr);
        while (waiter != nullptr) {
            explorer = waiter->next;
            while ((explorer != nullptr) && (explorer->val == waiter->val)) {
                explorer = explorer->next;
            }
            if (explorer == waiter->next) {
                return waiter;
            } else {
                waiter = explorer;
            }
        }
        return nullptr;
    }
};

二、递归法:

递归法一般思路清晰且代码量少,容易实现,但可能栈溢出,视问题情况而定。

本题共分四种情况:
一、→nullptr
二、→①→①→...→
三、→①→nullptr
四、→①→②→...→

class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        if (head == nullptr) {  // 第一种情况
            return head;
        }

        if ((head->next != nullptr) && (head->val == head->next->val)) {  // 第二种情况
            while ((head->next != nullptr) && (head->val == head->next->val)) {
                head = head->next;
            }
            return deleteDuplicates(head->next);  // 不建立连接关系,将删除重复后的节点作为头节点
        } else {  // 第三、四种情况
            head->next = deleteDuplicates(head->next);  // 建立连接关系
            return head;
        }
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值