LeetCode86:Partition List
来源:互联网 发布:开淘宝怎么拿货 编辑:程序博客网 时间:2024/05/20 20:45
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
/** 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; }};
- LeetCode86:Partition List
- LeetCode86 Partition List
- leetcode86. Partition List
- LeetCode86. Partition List
- leetcode86~Partition List
- leetcode86. Partition List
- LeetCode86. Partition List
- LeetCode86 Partition List
- LeetCode86——Partition List
- Leetcode86 - Partition List(链表)
- Partition List
- Partition List
- Partition List
- Partition List
- Partition List
- Partition List
- Partition List
- Partition List
- 相似性度量--Pearson相关系数
- ASP.NET checkBox value
- 新版AFNetworking2.5使用
- rust map的使用:获取某个key对应的value,如果不存在就插入一个
- 常用资源整理
- LeetCode86:Partition List
- [Python]网络爬虫(六):一个简单的百度贴吧的小爬虫
- 使用canvas画图
- vs中写和调试 mex
- 过程需要类型为 'ntext/nchar/nvarchar' 的参数 '@statement'
- 模板类里的friend方法
- 将Eclipse代码导入到Android Studio的两种方式
- opencv源码分析:cvCreateMTStumpClassifier最优弱分类器的代码框架
- RMQ 算法入门