环问题
如果两个没有环的链表相交于某一节点,那么在这个节点之后的所有节点都是两个链表共有的。
根据此特点,如果它们相交,则最后一个节点一定是共有的。那么只要判断两个链表的尾指针是否相等即可。
无环:
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; }
- 无环链表和有环链表是不可能相交的;
- 两个有环链表若相交,其“整个环上”的所有node一定都重合;
- 有环链表的相交,情况只有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;//返回头结点的下一个节点 } };