删除链表中重复的结点

剑指OFFER题47------按牛客网热度排序

时间:2019.1.16.1946
作者:Waitt

题目

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

时间限制:1秒 空间限制:32768K 热度指数:234318

解答

思路1

用一个栈q 依次存储结点地址,t指向当前栈顶结点在链表中的下一结点。
当发现t结点与栈顶结点相同时,将值赋给变量sh。
每次都判断栈顶是否与变量sh相同,若相同,则删除该结点并弹出栈顶,且让新的栈顶的next为t结点。
当栈为空或栈顶结点与t不相同时,则将t结点入栈,将t指向它的下一结点。重复循环直至尾节点。
若尾节点也为重复结点,则应将新的尾节点的next指针指向NULL。
栈底则为新链表的头节点。

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* deleteDuplication(ListNode* pHead)
    {
        if(!pHead)
            return pHead;
        stack<ListNode*> q;//存储结点指针的栈
        ListNode *hh;//指向删除完后链表的头节点
        ListNode *t;//指向栈q顶结点的链表中的下一个结点
        ListNode *s;//指向t的下一个结点
        int sh;//记录相同结点的值的变量
        t=s=pHead;
        q.push(t);//先存入第一个结点
        s=t->next;
        while(s)//每次循环仅删除一个结点
        {
            t=s;
            s=s->next;
            if(q.size()&&(q.top()->val)==(t->val))
            //确保可以访问q.top(),当当前栈顶的值与下一结点的值相等时
            {
                sh=(q.top()->val);//给sh赋值
            }
            if(q.size()&&(q.top()->val)==sh)
            //确保可以访问q.top(),当当前栈顶的值与sh值相等时,应该弹出删除该结点,并弹出栈顶
            {
                delete q.top();
                q.pop();
                if(q.size())
                    q.top()->next=t;
            }
            if(q.empty()||(q.top()->val)!=(t->val))
            //当栈为空或者栈顶结点值不等于下一结点值时,下一结点可入栈
            {
                q.push(t);
            }
        }
        if(q.size()&&(q.top()->val)==sh)
        //进行最后一个结点判断,当最后一个结点也为重复节点时,也应该删除该结点
        {
            delete q.top();
            q.pop();
            if(q.size())
                q.top()->next=NULL;//此处变为栈顶结点变为新链表的尾节点,所以应该指向NULL
        }
        while(q.size())//寻找新链表的头节点
        {
            hh=q.top();
            q.pop();
        }
        return hh;
    }
};

每次对q.top()进行访问时,应该和q.size()与运算,确保可以访问到q.top()。
例如:if(q.size()&&(q.top()->val)==(t->val))

思路2

四指针法,仅通过指针操作进行删除
每次大循环均需删除所有值相同的结点
分三种情况:
情况1:头结点在一直变化
情况2:头结点变化完毕,后续遍历发现重复结点
情况3:头结点变化完毕,后续遍历暂未发现重复结点

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* deleteDuplication(ListNode* pHead)
    {
        if(!pHead)
            return pHead;
        ListNode* a;//当前结点
        ListNode* b;//当前结点的下一结点
        ListNode* c=NULL;//新链表的头节点
        ListNode* d=NULL;//当前结点的上一结点
        c=a=b=pHead;
        b=a->next;
        while(b)//每次循环可以删除所有值相同的结点
        {
            bool i=0;//标志位,判断是否有重复出现
            while(b&&(a->val)==(b->val))//当出现重复时
            {
                i=1;//标志位置1
                delete a;
                a=b;
                b=a->next;
            }
            if(i==1)//说明有重复情况
            {
                i=0;//重置标志位
                if(d==NULL)//说明之前头结点一直在变动
                {
                    delete a;
                    a=b;
                    c=a;//赋值新的头结点
                    if(a)//当当前结点不为NULL时,才会有下一结点
                        b=a->next;
                }
                else//说明此时修改的不是头结点
                {
                    delete a;//删除当前结点
                    a=b;
                    d->next=a;//将上一结点的指针指向删除后的当前结点
                    if(a)//当当前结点不为NULL时,才会有下一结点
                        b=a->next;
                }
            }
            else//说明并无重复,d后移一位,a后移一位
            {
                d=a;
                a=b;
                if(a)
                    b=a->next;
            }
        }
        return c;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值