题解 | #删除链表中重复的结点#

删除链表中重复的结点

https://www.nowcoder.com/practice/fc533c45b73a41b0b44ccba763f866ef

//如果是未排序的链表,用桶来记录。但这题是已排序的,所以空间复杂度只要O1就够了。我们记录当前的节点,判断它与下一个节点是否相同即可。
//整体思路是简单的,但是一些细节处理比较麻烦。比如这题要求把所有重复的节点都删掉,比如1233445要求删除成125而不是12345,这要求我们把Previous也删掉,所以需要一个Entry来记录重复的入口节点。以便删除完一整串重复的数字后能将入口的next指向“对岸”
//再比如,有可能链表的开头就发生重复了,这样的话我们返回的链表的位置也必须从pHead往后挪。有可能还不止得挪一次。
//还比如,把整个链表删干净了的情况。
//落到实处时,还要考虑删完一段重复的节点后,接下来离链表结束只剩1个或0个节点的情况。
class Solution {
public:
    ListNode* deleteDuplication(ListNode* pHead) {
        if(pHead==nullptr || pHead->next==nullptr)//确保至少有两个节点
            return pHead;
        int Val=pHead->val;
        bool bDeletedHead=false;//是否删除掉了入口节点。
        bool bDeletedTail=false;//是否删除掉了尾巴
        ListNode* result=pHead;
        ListNode* currentNode=pHead->next;
        ListNode* PreviousNode=pHead;
        ListNode* Entry=new ListNode(-1);//重复的入口节点
        Entry->next=PreviousNode;
        int repeatedVal=0;//因为要把所有重复的值都删掉,而不是只删一个。
        int ListLength=0;//记录链表的长度,如果最后删干净了就返回空。
        while (currentNode) {
            if(currentNode->val==Val)//如果发生了重复,说明这时的Previous与currentNode都是重复的,都得删。但一个个来。
            {
                repeatedVal=currentNode->val;
                //说明在入口处就重复了,需要注意的是,入口可能会被多次删除。比如11122335678,这样的话,返回的result的位置要连续变3次。
                if(PreviousNode==result)
                    bDeletedHead=true;
                while (currentNode) {
                    if(currentNode->val==repeatedVal)
                    {
                        PreviousNode->next=currentNode->next;
                        delete currentNode;
                        currentNode=PreviousNode->next;
                        if(currentNode==nullptr)//说明链表末尾已被删
                            bDeletedTail=true;
                    }else {
                        break;
                    }
                }
                delete PreviousNode;
                PreviousNode=currentNode;
                if(bDeletedHead==true)
                {
                    result=PreviousNode;
                    bDeletedHead=false;//挪动一次result的位置,下次可能还得再挪,所以把其置为false。
                }
                if(bDeletedTail)//如果尾巴都删了那早该结束了
                {
                    Entry->next=nullptr;
                    return result;
                }
                Entry->next=PreviousNode;
                Val=PreviousNode->val;
                if(currentNode->next==nullptr)
                {
                    ListLength++;//如果删光这段重复的数字后,链表的后面还能剩2个节点,那就让currentNode再挪一格,一切正常进行。否则,代表后面只有一个节点了,currentNode没地方挪,剩下一个数字也不可能发生重复,我们让ListLength+1就结束。
                }
                currentNode=currentNode->next;
                continue;
            }else {
                Entry=PreviousNode;
                PreviousNode=currentNode;
                Val=PreviousNode->val;
                currentNode=currentNode->next;//如果没发生重复,都往前步进一格
                ListLength++;
            }
        }
        if(ListLength<=0)
            return nullptr;
        return result;
    }
};

全部评论

相关推荐

01-30 22:03
门头沟学院 Java
用微笑面对困难:我滴妈,【俩月】【实习】【主管】仨debuff吃满了,独立设计开发的项目写了绝大占比的运营板块,你独立开发,那维护、问题复盘、日志更新、bug、策划书全是自己整的? 不建议写那么大,可以从小出发更容易
点赞 评论 收藏
分享
刚刷到字节跳动官方发的消息,确实被这波阵仗吓了一跳。在大家还在纠结今年行情是不是又“寒冬”的时候,字节直接甩出了史上规模最大的转正实习计划——ByteIntern。咱们直接看几个最硬的数,别被花里胡哨的宣传词绕晕了。首先是“量大”。全球招7000多人是什么概念?这几乎是把很多中型互联网公司的总人数都给招进来了。最关键的是,这次的资源分配非常精准:研发岗给了4800多个Offer,占比直接超过六成。说白了,字节今年还是要死磕技术,尤其是产品和AI领域,这对于咱们写代码的同学来说,绝对是今年最厚的一块肥肉。其次是大家最关心的“转正率”。官方直接白纸黑字写了:整体转正率超过50%。这意味着只要你进去了,不划水、正常干,每两个人里就有一个能直接拿校招Offer。对于2027届(2026年9月到2027年8月毕业)的同学来说,这不仅是实习,这简直就是通往大厂的快捷通道。不过,我也得泼盆冷水。坑位多,不代表门槛低。字节的实习面试出了名的爱考算法和工程实操,尤其是今年重点倾斜AI方向,如果你简历里有和AI相关的项目,优势还是有的。而且,转正率50%也意味着剩下那50%的人是陪跑的,进去之后的考核压力肯定不小。一句话总结:&nbsp;27届的兄弟们,别犹豫了。今年字节这是铁了心要抢提前批的人才,现在投递就是占坑。与其等到明年秋招去千军万马挤独木桥,不如现在进去先占个工位,把转正名额攥在手里。
喵_coding:别逗了 50%转正率 仔细想想 就是转正与不转正
字节7000实习来了,你...
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务