剑指offer-链表

题目一:

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

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* deleteDuplication(ListNode* pHead)
    {
        if(pHead==NULL&&pHead->next==NULL) return pHead;
        ListNode* pre=NULL;      //可能用到的当前结点的前驱指针
        ListNode* now=pHead;     //当前处理结点指针
        ListNode* circP=NULL;    //循环重复结点的工具指针
        while(now!=NULL)
        {
            if(now->next!=NULL&&now->next->val==now->val) //当前结点和下个结点重复
            {                                             //可能在第一个结点就出现重复
                circP=now->next;                          //用工具指针去重
                while(circP!=NULL&&circP->val==now->val)
                {
                    circP=circP->next;
                }                                         //找到不重复的下个节点
                if(now==pHead)                            //当前结点是头节点也就是在链表头就    
                    pHead=circP;                          //出现重复
                else                                      //中间部分出现重复
                    pre->next=circP;
                now=circP;                                //可能出现4->4->5->5之类的连续重
            }                                             //复情况
            else
            {
                pre=now;                                  //当链表头部的重复去除掉后,在处理
                now=now->next;                            //中间部分的时候需要保留前驱结点指针
            }
        }
        return pHead;
    }
};

 

题目二:

给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* EntryNodeOfLoop(ListNode* pHead)
    {
        if(pHead==NULL||pHead->next==NULL) return NULL;   //没有环的情况,同时确保p和q有效
        ListNode* p=pHead->next->next;
        ListNode* q=pHead->next;
        while(p!=NULL&&p->next!=NULL&&p!=q)
        {
            p=p->next->next;
            q=q->next;
        }
        if(p==NULL||p->next==NULL) return NULL;           //没有环
        p=pHead;
        while(p!=q)
        {
            p=p->next;
            q=q->next;
        }
        return p;
    }
};

图解:

快指针以较满指针2倍的步率向前移动,相遇在红色标注处,假设环前的长度为L,环以顺时针方向,相遇点距离环的入口点的距离为m,环中剩余长度为n,则有:

                                   

 所以:

所以接下来让快指针回到头节点,以相同的步率前进,则再次相遇点一定在环的入口。

posted @ 2019-08-13 16:33  DH_HUSTer  阅读(11)  评论(0编辑  收藏  举报