给定一个链表,以及一个整数 target,将链表上小于这个target的节点移到大于等于target 的前面。
Input: head = 1->4->3->2->5->2, x = 3
Output: 1->2->2->4->3->5
思路:
用2个指针,slow和fast,slow指向小于大于等于target的前一个节点,即slow指向的是当前小于target的最后一个节点,移动fast,找到剩余节点中fast->next比target小的节点,然后将其移到slow的下一个节点,更新slow, fast 即可。为什么是比较slow->next / fast->next,而不是slow / fast,需要想明白节点的交换,需要前一个节点的指针,就算你找到当前节点是需要交换的节点,但你的前一个节点没有,就无法更新链表。
难点:
1.如果头结点大于等于target,也就是说头结点就需要交换,解决办法就是,在头结点前面放置一个我们自己申请的节点;
2.交换后fast的下一个节点改变了,此时不应该更新fast = fast->next,而是应该继续判断,新的fast->next 是否还需要交换。此处有点像75题的思路。
3.因为都是在判断slow->next, fast->next ,所以当slow/fast = NULL时,空指针->next就会报错,注意处理为空指针的情况。
class Solution { public: ListNode* partition(ListNode* head, int x) { if (!head || !head->next) return head; ListNode* res = new ListNode(-1), * slow = res, * fast = head; res->next = head; while (slow->next) { //首先找到需要在slow节点后面开始插入的地方 if (slow->next->val >= x) break; slow = slow->next; } fast = slow->next;//在slow后面开始找fast if (!fast) return res->next;//空指针判断 while (fast->next) { if (fast->next->val < x) { ListNode* tmpSlowNext = slow->next; ListNode* tmpFastNext = fast->next; fast->next = tmpFastNext->next; slow->next = tmpFastNext; tmpFastNext->next = tmpSlowNext; slow = slow->next; continue;//此时应该继续判断新的fast->next是否继续需要交换 } fast = fast->next; } return res->next; } };
稍微修改版:
class Solution { public: ListNode* partition(ListNode* head, int x) { if (!head || !head->next) return head; ListNode* res = new ListNode(-1), * slow = res, * fast = head; res->next = head; while (slow->next) { //首先找到需要在slow节点后面开始插入的地方 if (slow->next->val >= x) break; slow = slow->next; } fast = slow;//slow是一定非空,所以将 fast = slow,减少一次空指针判断 while (fast->next) { if (fast->next->val < x) { ListNode* tmpSlowNext = slow->next; ListNode* tmpFastNext = fast->next; fast->next = tmpFastNext->next; slow->next = tmpFastNext; tmpFastNext->next = tmpSlowNext; slow = slow->next; } else fast = fast->next; } return res->next; } };