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

删除链表中重复的结点

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;
    }
};

全部评论

相关推荐

1 收藏 评论
分享
牛客网
牛客企业服务