每日一算法题-去除链表重复节点

119 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情

一、题目

image.png

struct ListNode {
    int val;
    ListNode *next = nullptr;
    inline ListNode(int x, ListNode* next = nullptr) : val(x), next(next) { }
};

ListNode* removeRepeat(ListNode* pHead) {
}

int main(int, char**)
{
    ListNode p1(1);
    ListNode p2(2);
    ListNode p3(3);
    ListNode p4(3);
    ListNode p5(4);
    ListNode p6(4);
    ListNode p7(5);

    p1.next = &p2;
    p2.next = &p3;
    p3.next = &p4;
    p4.next = &p5;
    p5.next = &p6;
    p6.next = &p7;
    p7.next = nullptr;

    ListNode* node = removeRepeat(&p1);
    while(node){
        cout << node->val << endl;
        node = node->next;
    }

    return 0;
}

二、分析

根据题意可知

难点一:
需要获取链表中重复的节点
因为是单向链表,所以不能直接从右往左回溯,
这就造成要知道重复就得继续走,走了又回不来,
这个时候就只能遍历的时候同时判断当前节点和下一节点是否相等,
相等就继续走,把所有相等节点全部走完,
不相等就可以保留下来。
由于相等要继续走,不能单纯通过if来判断是否要保留,
所以需要一个状态量,记录此次遍历的结果。

容易忽略1:
假如最后一个有效节点后面有无效节点,还需要手动将有效节点的指向置空,因为它才是真正的尾节点

容易忽略2:
假如首节点是重复节点,首节点被过滤了之后就没有首节点了,所以还必须有一个新表头来放有效节点

三、实现

ListNode* removeRepeat(ListNode* pHead) {
    if(pHead==nullptr || pHead->next==nullptr)return pHead;
    ListNode result(0);
    result.next = pHead;
    ListNode* cur = &result;
    bool repeat = false;
    while(pHead){
        while(pHead->next && pHead->val == pHead->next->val){
            pHead = pHead->next;
            repeat = true;
        }
        if(repeat){
            repeat = false;
        }else{
            cur->next = pHead;
            cur = pHead;
        }
        pHead = pHead->next;
    }
    cur->next = nullptr;
    return result.next;
}

四、结言

这道题的关键在于细节的处理,有些很容易被忽视的点往往会造成解题一直无法通过,造成心理压力,从而恶性循环。
解题的时候要全面分析各种情况,才能无往而不利。

创作不易,留个赞再走吧!如果对文章内容有任何指正,欢迎评论!