题目介绍:
思路:创建两个链表,ghead尾插大于x的节点,lhead尾插小于x的节点。先遍历链表。最后将ghead尾插到lhead后面,将大小链表链接。
我们需要在创建两个链表指针,指向两个链表的头节点,用这两个指针标记lhead和ghead的尾结点,方便与尾插。
注:极端边界场景:所有值都小于x; 所有值都大于x; 空链表。
- /*
- struct ListNode {
- int val;
- struct ListNode *next;
- ListNode(int x) : val(x), next(NULL) {}
- };*/
-
-
- class Partition {
- public:
- ListNode* partition(ListNode* pHead, int x)
- {
- ListNode* gtail, * ghead, * ltail, * lhead;
- gtail = ghead = (struct ListNode*)malloc(sizeof(struct ListNode));
- ltail = lhead = (struct ListNode*)malloc(sizeof(struct ListNode));
- struct ListNode* cur = pHead;
- while (cur)
- {
- if (cur->val < x)
- {
- ltail->next = cur;
- ltail = ltail->next;
- }
- else
- {
- gtail->next = cur;
- gtail = gtail->next;
- }
- cur = cur->next;
- }
- ltail->next = ghead->next;
- gtail->next = NULL;
- struct ListNode* newhead = lhead->next;
- free(lhead);
- free(ghead);
- return newhead;
- }
- };
题目介绍:

思路:先找到中间节点,可以利用快慢指针找到中间节点,然后将中间节点后面的节点翻转,在和中间节点前面的链表依次比较,如果全部相同则是回文链表否则不是。
- /*
- struct ListNode {
- int val;
- struct ListNode *next;
- ListNode(int x) : val(x), next(NULL) {}
- };*/
- //struct ListNode* middleNode(struct ListNode* head)
- {
- struct ListNode* falst;
- struct ListNode* slow;
- falst = head;
- slow = head;
- while (falst && falst->next)
- {
- slow = slow->next;
- falst = falst->next->next;
- }
- return slow;
- }
- struct ListNode* reverseList(struct ListNode* head)
- {
- struct ListNode* cur = head;
- struct ListNode* newhead = NULL;
- while (cur)
- {
- struct ListNode* next = cur->next;
- //头插
- cur->next = newhead;
- newhead = cur;
-
- cur = next;
- }
- return newhead;
- }
-
- class PalindromeList
- {
- public:
- bool chkPalindrome(ListNode* head)
- {
- //找到中间节点,将中间节点后面的链表翻转,有第一个和中间节点比较,并依次后移,若全部相同,则为回文链表,反之不是。
- struct ListNode* mid = middleNode(head);
- struct ListNode* rmid = reverseList(mid);
- while (rmid && mid)
- {
- if (rmid->val != head->val)
- {
- return false;
- }
- head = head->next;
- rmid = rmid->next;
- }
- return true;
- }
-
- };
题目介绍:



思路:先遍历两个链表,计算出两个链表的长度,让后计算出两个链表的长度差k,将长的链表先往前走k步,然后将两个链表指针同时后移,找到第一个相同的节点就是相交节点。
注:需要考虑到空链表,给链表判空,若空headA和headB其中一个为空返回NULL。
- /**
- * Definition for singly-linked list.
- * struct ListNode {
- * int val;
- * struct ListNode *next;
- * };
- */
- struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB)
- {
- struct ListNode* curA = headA;
- struct ListNode* curB = headB;
- int lenA = 1;
- int lenB = 1;
- if(headA==NULL||headB==NULL)
- {
- return NULL;
- }
- while (curA->next)
- {
- curA = curA->next;
- lenA++;
- }
- while (curB->next)
- {
- curB = curB->next;
- lenB++;
- }
- if (curA != curB) //没有交点
- {
- return false;
- }
- int gap = abs(lenA - lenB);
- struct ListNode* falst = headA;
- struct ListNode* slow = headB;
- if (lenA < lenB)
- {
- falst = headB;
- slow = headA;
- }
- while (gap--)
- {
- falst = falst->next;
- }
- while (slow != falst)
- {
- slow = slow->next;
- falst = falst->next;
- }
- return slow;
- }
题目介绍:



思路:还是利用快慢指针,当慢指针往前走一步,快指针往前走两步,在一个环中,每次他们的距离就减少一,如果有环,就一定能追上。如果没追上则没有环。
用快指针遍历。
- /**
- * Definition for singly-linked list.
- * struct ListNode {
- * int val;
- * struct ListNode *next;
- * };
- */
- bool hasCycle(struct ListNode *head)
- {
- struct ListNode *falst=head;
- struct ListNode *slow=head;
- while(falst&&falst->next)
- {
- falst=falst->next->next;
- slow=slow->next;
- if(falst==slow)
- {
- return true;
- }
-
- }
- return false;
- }
题目描述:


思路1:假设链表带环,头节点head与入环节点的距离为L,入环节点与相遇点的距离为D,环的大小为C,如下图:

fast从头节点到相遇点:L + D + kC,其中k为正整数,表示在快慢指针相遇前fast所走圈数
slow从头节点到相遇点:L + D
又由于fast每次走两步,slow每次走一步,以上二式可以建立起联系:
L + D + kC = 2 * (L + D)
L = kC - D = (k - 1) * C + C - D
所以可以得出结论:一个指针从相遇点开始走,一个指针从链表头开始走,则这两个指针一定会在入环节点处相遇。
- struct ListNode *detectCycle(struct ListNode *head) {
- struct ListNode *fast=head, *slow=head;
- while(fast && fast->next)
- {
- fast=fast->next->next;
- slow = slow->next;
- if(fast == slow)
- {
- //找相遇点meetNode
- struct ListNode* meetNode = fast;
- //相遇点可能就是入环节点
- if(meetNode == head)
- return head;
- //meetNode和head开始每次走一步,直到相遇
- while(head && meetNode)
- {
- meetNode = meetNode->next;
- head = head->next;
- //当相遇时即为入环节点
- if(meetNode == head)
- return meetNode;
- }
- }
- }
- return NULL;
- }
思路2:我们可以在相遇点将链表断开,找到如节点就相当于找到两个链表的交点。
找两个链表的交点我们可以参考题目三
- struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB)
- {
- struct ListNode *curA=headA;
- struct ListNode *curB=headB;
- int lenA=1;
- int lenB=1;
- while(curA->next)
- {
- curA=curA->next;
- lenA++;
- }
- while(curB->next)
- {
- curB=curB->next;
- lenB++;
- }
- if(curA!=curB) //没有交点
- {
- return false;
- }
- int gap=abs(lenA-lenB);
- struct ListNode *falst=headA;
- struct ListNode *slow=headB;
- if(lenA<lenB)
- {
- falst=headB;
- slow=headA;
- }
- while(gap--)
- {
- falst=falst->next;
- }
- while(slow!=falst)
- {
- slow=slow->next;
- falst=falst->next;
- }
- return slow;
- }
- struct ListNode *detectCycle(struct ListNode *head)
- {
- struct ListNode *fast=head;
- struct ListNode *slow=head;
- while(fast&&fast->next)
- {
- slow=slow->next;
- fast=fast->next->next;
- if(slow==fast) //相遇了
- {
- struct ListNode *meet=slow; //将环断开
- struct ListNode *newhead=meet->next;
- meet->next=NULL;
- return getIntersectionNode(head,newhead); //找两个链表的交点
- }
- }
- return NULL;
- }