数据结构-剑指offer-删除链表中的重复节点

38 篇文章 0 订阅
38 篇文章 0 订阅

题目:在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。例如,链表1->2->3->3->4->4->5 处理后为 1->2->5

思路:首先这是一个已经排序好的链表,所以从头开始遍历碰到重复的不输出。可以采用循环的方法,也可以采取递归的方法。

以1->2->2->2->4->4->5为例,演示下示过程,帮助理解

代码1:循环

问题:return出现问题


class Solution {
public:
    ListNode* deleteDuplication(ListNode* pHead)
    {
        if(pHead == nullptr || pHead->next == nullptr)
            return;
        ListNode* pPreNode = nullptr;
        ListNode* pNode = pHead;
        while(pNode != nullptr){
            ListNode* pNext = pNode->next;
            bool needDelete = false;
            if(pNext != nullptr && pNext->val == pNode->val)
                needDelete = true;
            if(!needDelete){
                //如果false,则当前节点赋值给前节点,下一个节点赋值给当前节点
                pPreNode = pNode;
                pNode = pNode->next;
            }
            else{
                //如果下一个节点pNext的值与pNode的值相同,存储该值
                int value = pNode->val;
                //如果pNode的值与pNext相同,定义一个指针用来存储当前待删除的节点
                ListNode* toBeDelete = pNode;
                while(toBeDelete != nullptr && toBeDelete->val == value){
                    pNext = toBeDelete->next;
                    delete toBeDelete;
                    toBeDelete = nullptr;
                    toBeDelete = pNext;
                    if(pPreNode == nullptr)
                        pHead = pNext;
                    else
                        pPreNode->next = pNext;
                    pNode = pNext;
                }
            }
        }
        return pHead;
    }
};

代码2:递归

class Solution {
public:
    ListNode* deleteDuplication(ListNode* pHead)
    {
        if(pHead == nullptr || pHead->next == nullptr)
            return pHead;
        ListNode* current;
        if(pHead->val == pHead->next->val){
            current = pHead->next->next;
            while(current != nullptr && current->val == pHead->val)
                //跳过与当前节点不同的节点,直到第一个与当前节点不同的节点。
                current = current->next;
            //从第一个与当前结点不同的结点开始递归
            return deleteDuplication(current);
        }
        else{
            current = pHead->next;
            //如果当前节点不是重复节点,则保留当前节点,从下一个结点开始递归
            pHead->next = deleteDuplication(current);
            return pHead;
        }
    }
};
class Solution {
public:
    ListNode* deleteDuplication(ListNode* pHead)
    {
        if(pHead == nullptr || pHead->next == nullptr)
            return pHead;
        ListNode* p = pHead;
        ListNode* head = new ListNode(pHead->val+1);
        head->next = p;
        ListNode* q = head;
        while(p){
            //值相等,指针p后移
            while(p->next && p->next->val == p->val){
                p = p->next;
            }
            //没有相等的值,两个指针都往后移
            if(q->next == p){
                p = p->next;
                q = q->next;
            }
            else{
                q->next = p->next;
                p = p->next;
            }
        }
        return head->next;
    }
};

代码3:讨论区还有一种方法,创建一个头节点和两个指针p、q

class Solution {
public:
    ListNode* deleteDuplication(ListNode* pHead)
    {
        if(pHead == nullptr || pHead->next == nullptr)
            return pHead;
        ListNode* p = pHead;
        //新建一个头节点head,令他的值为真正的头节点的值+1
        ListNode* head = new ListNode(pHead->val+1);
        //定义两个指针p、q。;两个指针用来比较节点的值
        //p指向自建的头节点head的下一个节点pHead(也就是真正的头节点)
        head->next = p;
        //新建头节点q、指向自己定义的头节点
        ListNode* q = head;
        while(p){
            //值相等,指针p后移
            while(p->next && p->next->val == p->val){
                p = p->next;
            }
            //没有相等的值,两个指针都往后移
            if(q->next == p){
                p = p->next;
                q = q->next;
            }
            else{
                //如果两个节点指向的值相等,令q的next指向p的next,调过相同的节点
                q->next = p->next;
                p = p->next;
            }
        }
        //从真正的头节点pHead开始返回值
        return head->next;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值
>