96 链表划分
原题网址:http://www.lintcode.com/zh-cn/problem/partition-list/
给定一个单链表和数值x,划分链表使得所有小于x的节点排在大于等于x的节点之前。
你应该保留两部分内链表节点原有的相对顺序。
您在真实的面试中是否遇到过这个题?
Yes
样例
给定链表 1->4->3->2->5->2->null,并且 x=3
返回 1->2->2->4->3->5->null
标签
看到这道题懵逼很久,思路一直不清晰,后来码码删删冒出一个想法:
1.可以定义一个ListNode*类型的right,存放大于等于x的节点,即遍历原链表,如果找到大于或等于x的节点,将其赋值给right,结束遍历;
2.然后新建一个链表newList存放小于x的节点,再次遍历原链表,如果当前节点小于x,将其挂载到newList上,再将该节点从原链表中删除,继续遍历下一个节点;
3.最后,将right挂载到newList上。
AC代码:
/** * Definition of singly-linked-list: * class ListNode { * public: * int val; * ListNode *next; * ListNode(int val) { * this->val = val; * this->next = NULL; * } * } */ class Solution { public: /** * @param head: The first node of linked list * @param x: An integer * @return: A ListNode */ ListNode * partition(ListNode * head, int x) { // write your code here if (head==NULL) { return NULL; } ListNode *right=NULL;//大于等于x的第一个节点; ListNode *index=head;//保存头结点; while(head!=NULL) { if (head->val>=x) { right=head; break; } head=head->next; } ListNode * newList=new ListNode(0);//新链表头结点; ListNode *result=newList; ListNode *pre=NULL; while(index!=NULL) { if (index->val<x) { newList->next=new ListNode(index->val); newList=newList->next; //删除index; if (pre!=NULL) { pre->next=index->next; } else { pre=index; } } else { pre=index; } index=index->next; } newList->next=right; return result->next; } };
注意:第2步挂载小于x的节点到newList上时,一定要new出新的节点再挂载,不可直接赋值,如以下代码(通过66%的数据):
直接赋值的话可能造成错误,当原链表中小于x的节点中间没有间隔时,删除操作也将newList中相同节点删除了……多个指针指向同一个目标的隐患,吐血。
但如果是例子中给出的1->4->3->2->5->2->null,大于x和小于x的节点间隔开就可以得到正确结果……要警惕测试数据不足时的正确代码啊,哭,指针操作需谨慎。
ListNode * partition(ListNode * head, int x) { // write your code here if (head==NULL) { return NULL; } ListNode *right=NULL;//大于x的第一个节点; ListNode *index=head;//保存头结点; while(head!=NULL) { if (head->val>=x) { right=head; break; } head=head->next; } ListNode * newList=new ListNode(0);//保存新链表头结点; ListNode *result=newList; ListNode *pre=NULL; while(index!=NULL) { if (index->val<x) { newList->next=index; newList=index; //删除index; if (pre!=NULL) { pre->next=index->next; } else { pre=index; } } else { pre=index; } index=index->next; } newList->next=right; return result->next; }
最后上网一查发现还有更好的思路,就是标签里的两根指针,参考如下:
https://blog.csdn.net/lfj17/article/details/66590654
https://www.jiuzhang.com/solutions/partition-list/
AC代码:
/** * Definition of singly-linked-list: * class ListNode { * public: * int val; * ListNode *next; * ListNode(int val) { * this->val = val; * this->next = NULL; * } * } */ class Solution { public: /** * @param head: The first node of linked list * @param x: An integer * @return: A ListNode */ ListNode * partition(ListNode * head, int x) { // write your code here if (head==NULL) { return NULL; } ListNode * leftDummy=new ListNode(0); //保存头结点; ListNode * rightDummy=new ListNode(0); ListNode *left=leftDummy;//左侧当前节点; ListNode *right=rightDummy; while(head!=NULL) { if (head->val<x) { left->next=head; left=head; } else { right->next=head; right=head; } head=head->next; } right->next=NULL; left->next=rightDummy->next; return leftDummy->next; } };