LeetCode86:Partition List
2015-06-10 16:19
627 查看
Given a linked list and a value x, partition it such that all nodes less than x come before nodes greater than or equal to x.
You should preserve the original relative order of the nodes in each of the two partitions.
For example,
Given 1->4->3->2->5->2 and x = 3,
return 1->2->2->4->3->5.
链表的分割,将链表中的元素分成两个部分,小于x的元素都在大于或等于x的元素的左边。并保持元素的相对顺序。
最开始想用快排的思想,发现快排会打乱相对顺序,行不通。
然后想到了冒泡排序的思想,在纸上画了个草图,发现有一定的可行性,但是其中会有大量的判断分支。
基本的思想如下:
初始定义一个伪指针fakeNode,它的next指针指向head。
然后定义一个prev指针,这个指针初始和fakeNode一样。因为后面会有指针的删除操作,所以需要保存被删除元素的前一个节点,故这里prev指针指向第一个小于x的前一个元素。
寻找到第一个小于x的前一个节点,此时prev指针指向它
如过找到的这个节点不为空并且这个节点不是头节点,那么需要调整指针,使这个节点放置到链表的最前面,并且更新prev的位置指向第一个小于x的元素。
如过找到的这个节点不为空并且这个节点是头节点,将prev指针移动一个位置,是prev指向第一个小于x的元素。
如过找到的这个节点为空,表示数组中所有元素都大于x,此时可以直接返回。
然后就可以用另外一个指针iter遍历链表,当这个元素小于x时,将它插入prev后面。
runtime:8ms
上面的代码估计除了第一次见到时会这样编码,知道技巧了后就再也不会这么写了。但是上面也是一种正确的解法,在leetcode中也测试通过了,runtime为8ms,速度也是比较快的。只是对于编写代码的人而言工作量会有点大。但是从中也学到了一些技巧。
链表的删除操作室相对整个算法而言是相当复杂的,因为它需要保存被删除节点的前一个指针,所以可能会有可以避免删除操作的方法。
伪指针在链表操作中是一种很好的技巧。
如果真的需要需要删除节点,最好使用两个指针,一个指向当前节点,一个指向它之前的节点。
解法二:
第二种解法相当巧妙,代码也很简单,写起来也不那么容易出错。可以发现优秀的算法实现起来也是很容易的。
它将链表分成了两个链表,一个链表中的元素都小于x,另外一个链表中的元素都大于等于x。这样就能保证相对顺序了。
You should preserve the original relative order of the nodes in each of the two partitions.
For example,
Given 1->4->3->2->5->2 and x = 3,
return 1->2->2->4->3->5.
链表的分割,将链表中的元素分成两个部分,小于x的元素都在大于或等于x的元素的左边。并保持元素的相对顺序。
最开始想用快排的思想,发现快排会打乱相对顺序,行不通。
然后想到了冒泡排序的思想,在纸上画了个草图,发现有一定的可行性,但是其中会有大量的判断分支。
基本的思想如下:
初始定义一个伪指针fakeNode,它的next指针指向head。
然后定义一个prev指针,这个指针初始和fakeNode一样。因为后面会有指针的删除操作,所以需要保存被删除元素的前一个节点,故这里prev指针指向第一个小于x的前一个元素。
寻找到第一个小于x的前一个节点,此时prev指针指向它
如过找到的这个节点不为空并且这个节点不是头节点,那么需要调整指针,使这个节点放置到链表的最前面,并且更新prev的位置指向第一个小于x的元素。
如过找到的这个节点不为空并且这个节点是头节点,将prev指针移动一个位置,是prev指向第一个小于x的元素。
如过找到的这个节点为空,表示数组中所有元素都大于x,此时可以直接返回。
然后就可以用另外一个指针iter遍历链表,当这个元素小于x时,将它插入prev后面。
runtime:8ms
/** 1. Definition for singly-linked list. 2. struct ListNode { 3. int val; 4. ListNode *next; 5. ListNode(int x) : val(x), next(NULL) {} 6. }; */ class Solution { public: ListNode* partition(ListNode* head, int x) { if(head==NULL||head->next==NULL) return head; ListNode * fakeNode=new ListNode(0); ListNode * prev=fakeNode; fakeNode->next=head; ListNode * iter=head; //找到第一个下一个元素大于等于x的节点 while(prev->next!=NULL&&prev->next->val>=x) prev=prev->next; if(prev->next!=NULL&&prev->next!=head) { ListNode * tmp=prev->next; prev->next=tmp->next; tmp->next=head; fakeNode->next=tmp; iter=prev; prev=tmp; } else if(prev->next!=NULL&&prev->next==head) { prev=prev->next; } else{ return fakeNode->next; } while(iter->next!=NULL) { if(iter->next->val<x) { if(iter==prev) { iter=iter->next; prev=prev->next; } else { ListNode * tmp=iter->next; iter->next=iter->next->next; tmp->next=prev->next; prev->next=tmp; prev=prev->next; } } else iter=iter->next; } return fakeNode->next; } };
上面的代码估计除了第一次见到时会这样编码,知道技巧了后就再也不会这么写了。但是上面也是一种正确的解法,在leetcode中也测试通过了,runtime为8ms,速度也是比较快的。只是对于编写代码的人而言工作量会有点大。但是从中也学到了一些技巧。
链表的删除操作室相对整个算法而言是相当复杂的,因为它需要保存被删除节点的前一个指针,所以可能会有可以避免删除操作的方法。
伪指针在链表操作中是一种很好的技巧。
如果真的需要需要删除节点,最好使用两个指针,一个指向当前节点,一个指向它之前的节点。
解法二:
第二种解法相当巧妙,代码也很简单,写起来也不那么容易出错。可以发现优秀的算法实现起来也是很容易的。
它将链表分成了两个链表,一个链表中的元素都小于x,另外一个链表中的元素都大于等于x。这样就能保证相对顺序了。
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: //解法二:分离成两个链表,一个链表中的元素都比x小,另外一个都大即可 //也需要使用伪节点 ListNode* partition(ListNode* head, int x) { ListNode * small=new ListNode(0),*small_tail=small; ListNode * big=new ListNode(0),*big_tail=big; ListNode * cur=head; while(cur!=NULL) { if(cur->val<x) { small_tail->next=cur; small_tail=small_tail->next; cur=cur->next; small_tail->next=NULL;//这一步需要将加到small_tail尾端的next指针置为NULL,否则返回值中可能会出现循环 } else { big_tail->next=cur; big_tail=big_tail->next; cur=cur->next; big_tail->next=NULL; } } small_tail->next=big->next; return small->next; } };
相关文章推荐
- 16 行为型模式-----备忘录模式
- 原来老外也喜欢盖楼
- sql having 函数 按匿名字段作为条件进行查询
- Android基础教程(二)之五大布局对象---FrameLayout,LinearLayout ,AbsoluteLayout,RelativeLayout,TableLayout.
- android多个fragment返回键层层返回
- [Python]网络爬虫(五):urllib2的使用细节与抓站技巧
- 统计c程序的一个设计,牛小芙老大的课程设计。觉得不错,收藏了。
- Unity5.0.2工程出现的错误处理
- 索引键的唯一性(3/4):唯一聚集索引上的唯一和非唯一非聚集索引
- 索引键的唯一性(2/4):唯一与非唯一聚集索引
- 用Go语言做产品半年的一些感觉
- ZeroMQ的进阶
- 2-3 矢量格式图像-1-4
- mysql 不能对同一个表进行 update(delete) 和 select 联合操作
- NSString
- win2008 R2 64位系统下配置DCOM权限
- GRE逻辑写作解析
- cocos2.x cocos3.x创建命令
- Java 面试题
- 【工具使用】secureCRT中的中文乱码问题