链表常考题型

链表问题集锦

环问题

如果两个没有环的链表相交于某一节点,那么在这个节点之后的所有节点都是两个链表共有的。

根据此特点,如果它们相交,则最后一个节点一定是共有的。那么只要判断两个链表的尾指针是否相等即可。

无环:
bool
isIntersect(ListNode *n1,ListNode *n2) {   if(n1==NULL||n2==NULL)return false;   while(n1->next!=NULL){     n1=n1->next;   }   while(n2->next!=NULL){     n2=n2->next;   }   if(n1==n2)return true;   else return false; }
  1. 无环链表和有环链表是不可能相交的;
  2. 两个有环链表若相交,其“整个环上”的所有node一定都重合;
  3. 有环链表的相交,情况只有2种:相交于”环上”或相交于”不是环的部分”,即下图所示;

分析:如果有环且两个链表相交,则两个链表都有共同一个环,即环上的任意一个节点都存在于两个链表上。因此,就可以判断一链表上俩指针相遇的那个节点,在不在另一条链表上。

//判断单链表是否存在环,参数circleNode是环内节点,后面的题目会用到  
bool hasCircle(Node *head,Node *&circleNode)  
{  
    Node *slow,*fast;  
    slow = fast = head;  
    while(fast != NULL && fast->next != NULL)  
    {  
        fast = fast->next->next;  
        slow = slow->next;  
        if(fast == slow)  
        {  
            circleNode = fast;  
            return true;  
        }  
    }  
  
    return false;  
}  
//判断两个带环链表是否相交  
bool isIntersectWithLoop(Node *h1,Node *h2)  
{  
    Node *circleNode1,*circleNode2;  
    if(!hasCircle(h1,circleNode1))    //判断链表带不带环,并保存环内节点  
        return false;                //不带环,异常退出  
    if(!hasCircle(h2,circleNode2))  
        return false;  
  
    Node *temp = circleNode2->next;  
    while(temp != circleNode2)  
    {  
        if(temp == circleNode1)  
            return true;  
        temp = temp->next;  
    }  
    return false;  
}  

 求环的长度

int GetCirLen(ListNode *pHead)
{
    ListNode *pMeet = IsCircle(pHead);//IsCircle函数返回slow与fast相交的节点
    int count = 0;
    if (pMeet)//带环
    {
        ListNode *pNext = pMeet;
        while (pNext->_next != pNext)
        {
            count++;
            pNext = pNext->_next;
        }
        count++;//算上最后一个结点
    }
    return count;
}

 


 

删除一个排序链表中重复的节点

class Solution {
public:
    ListNode* deleteDuplication(ListNode* pHead)
    {
        if(pHead==NULL||pHead->next==NULL) return pHead;
              //新建一个节点,防止头结点要被删除
        ListNode* newHead=new ListNode(-1);
        newHead->next=pHead;
        ListNode* pre=newHead;//pre是要删除的最前面重复节点的前一个节点
        ListNode* cur=pHead;
        ListNode* pnext=NULL;
        while(cur!=NULL && cur->next!=NULL)
        {
            pnext=cur->next;
            if(cur->val==pnext->val)//如果当前节点的值和下一个节点的值相等
            {
                while(pnext!=NULL && pnext->val==cur->val)//向后重复查找
                    pnext=pnext->next;
                pre->next=pnext;//指针赋值,就相当于删除
                cur=pnext;
            }
            else//如果当前节点和下一个节点值不等,则向后移动一位
            {
                pre=pre->next;
                cur=cur->next;
            }
        }
        return newHead->next;//返回头结点的下一个节点
    }
               
};

 

posted @ 2018-06-21 10:10  追逐更好的自己  阅读(254)  评论(0编辑  收藏  举报