数据结构与算法分析笔记与总结(java实现)--链表11:链表按值分化问题
2017-01-17 21:26
603 查看
题目:对于一个链表,我们需要用一个特定阈值完成对它的分化,使得小于等于这个值的结点移到前面,大于该值的结点在后面,同时保证两类结点内部的位置关系不变。给定一个链表的头结点head,同时给定阈值val,请返回一个链表,使小于等于它的结点在前,大于等于它的在后,保证结点值不重复。
测试样例:
{1,4,2,5},3
{1,2,4,5}
思路一:将链表元素放到一个数组中,在数组中实现分化,将小于val的值移动到左边,将大于val的值移动到右边,最后再将其串联成为链表即可。类似于荷兰国旗问题,使用了额外的空间复杂度。
思路二:将单链表分化成为3条链表,遍历链表,小于val的结点形成一条链表list1,等于val的结点形成一条链表list2,大于val的结点形成一条链表list3,然后再将list1,list2,list3连接起来返回头结点即可。
{1620,1134,861,563,1},1134对应输出应该为:{1134,861,563,1,1620}你的输出为:{861,563,1,1134,1620}
注意理解清楚题目的意思:即整个链表应该分成2个部分而不是3个部分,对于分界值val,遍历链表,将小于或者等于val的结点组成链表list1,将大于val的结点放到链表list2,于是即使有等于val的结点,塔门依然是分隔开的,而不是全部集中在一起。思路还是一样的,只是对于题目的理解要准确。
这里要注意几个点:关于引用关系的深入理解:
非常关键点①:千万注意这里:list1、list2的最后一个结点都是引用了list,而list是一整条链表,因此list1,list2在需要保留的结点之后还会拖带这list上面的结点,这是不准确的因此必须将list1,list2尾巴后面list链表的值切断。总结:如果新的链表list1需要对原链表摸个结点之后的全部结点进行引用那么就直接将list赋值给新链表即可,如果新链表list1只需要原链表list上面的某几个结点,那么在list1从list上获取到最后一个需要的结点之后就要手动将list1的next置为null,来切断关联。
非常关键点②:当前resultList指向的是head1链表的头结点,要使得head2能够连接到其尾部需要将resultList指针移动到head1尾部。
public class Divide {
public ListNode listDivide(ListNode head, intval) {
//特殊的输入
if(head==null) return null;
//构造3条链表,每条链表都要记住头结点
ListNode head1=new ListNode(-1);
ListNode head2=new ListNode(-1);
ListNode list1=head1;
ListNode list2=head2;
//对输入的主链表进行遍历
ListNode list=head;
while(list!=null){
if(list.val<=val){
list1.next=list;
list1=list1.next;
}else if(list.val>val){
list2.next=list;
list2=list2.next;
}
list=list.next;
}
/*非常关键点①:千万注意这里:list1、list2的最后一个结点都是引用了list,而list是一整条链表,因此list1,list2在需要保留的结点之后还会拖带这list上面的结点,这是不准确的因此必须将list1,list2尾巴后面list链表的值切断。总结:如果新的链表list1需要对原链表摸个结点之后的全部结点进行引用那么就直接将list赋值给新链表即可,如果新链表list1只需要原链表list上面的某几个结点,那么在list1从list上获取到最后一个需要的结点之后就要手动将list1的next置为null,来切断关联。*/
if(list1.next!=null) list1.next=null;
if(list2.next!=null) list2.next=null;
/*已经得到list1,list2,list3,将其连接起来即可;注意:只有不为空的才可以被连接;如果直接连接list1,list2,list3,那么要对list1,list2,list3中
某个项为null进行判断,存在很多种情况,十分麻烦;所以解决方案是重新建立一个链表resultList,将不为null的链表连接到resultList即可。*/
ListNode dummy=new ListNode(-1);
ListNode resultList=dummy;
//说明小于链存在,将其连接到resultList上
if(head1.next!=null){
resultList.next=head1.next;
//非常关键点②:当前resultList指向的是head1链表的头结点,要使得head2能够连接到其尾部需要将resultList指针移动到head1尾部
while(head1.next!=null){
resultList=resultList.next;
head1=head1.next;
}
}
//说明等于链存在,将其连接到resultList上
if(head2.next!=null) {
resultList.next=head2.next;
while(head2.next!=null){
resultList=resultList.next;
head2=head2.next;
}
}
//说明大于链存在,将其连接到resultList上
return dummy.next;
}
}
测试样例:
{1,4,2,5},3
{1,2,4,5}
思路一:将链表元素放到一个数组中,在数组中实现分化,将小于val的值移动到左边,将大于val的值移动到右边,最后再将其串联成为链表即可。类似于荷兰国旗问题,使用了额外的空间复杂度。
思路二:将单链表分化成为3条链表,遍历链表,小于val的结点形成一条链表list1,等于val的结点形成一条链表list2,大于val的结点形成一条链表list3,然后再将list1,list2,list3连接起来返回头结点即可。
{1620,1134,861,563,1},1134对应输出应该为:{1134,861,563,1,1620}你的输出为:{861,563,1,1134,1620}
注意理解清楚题目的意思:即整个链表应该分成2个部分而不是3个部分,对于分界值val,遍历链表,将小于或者等于val的结点组成链表list1,将大于val的结点放到链表list2,于是即使有等于val的结点,塔门依然是分隔开的,而不是全部集中在一起。思路还是一样的,只是对于题目的理解要准确。
这里要注意几个点:关于引用关系的深入理解:
非常关键点①:千万注意这里:list1、list2的最后一个结点都是引用了list,而list是一整条链表,因此list1,list2在需要保留的结点之后还会拖带这list上面的结点,这是不准确的因此必须将list1,list2尾巴后面list链表的值切断。总结:如果新的链表list1需要对原链表摸个结点之后的全部结点进行引用那么就直接将list赋值给新链表即可,如果新链表list1只需要原链表list上面的某几个结点,那么在list1从list上获取到最后一个需要的结点之后就要手动将list1的next置为null,来切断关联。
非常关键点②:当前resultList指向的是head1链表的头结点,要使得head2能够连接到其尾部需要将resultList指针移动到head1尾部。
public class Divide {
public ListNode listDivide(ListNode head, intval) {
//特殊的输入
if(head==null) return null;
//构造3条链表,每条链表都要记住头结点
ListNode head1=new ListNode(-1);
ListNode head2=new ListNode(-1);
ListNode list1=head1;
ListNode list2=head2;
//对输入的主链表进行遍历
ListNode list=head;
while(list!=null){
if(list.val<=val){
list1.next=list;
list1=list1.next;
}else if(list.val>val){
list2.next=list;
list2=list2.next;
}
list=list.next;
}
/*非常关键点①:千万注意这里:list1、list2的最后一个结点都是引用了list,而list是一整条链表,因此list1,list2在需要保留的结点之后还会拖带这list上面的结点,这是不准确的因此必须将list1,list2尾巴后面list链表的值切断。总结:如果新的链表list1需要对原链表摸个结点之后的全部结点进行引用那么就直接将list赋值给新链表即可,如果新链表list1只需要原链表list上面的某几个结点,那么在list1从list上获取到最后一个需要的结点之后就要手动将list1的next置为null,来切断关联。*/
if(list1.next!=null) list1.next=null;
if(list2.next!=null) list2.next=null;
/*已经得到list1,list2,list3,将其连接起来即可;注意:只有不为空的才可以被连接;如果直接连接list1,list2,list3,那么要对list1,list2,list3中
某个项为null进行判断,存在很多种情况,十分麻烦;所以解决方案是重新建立一个链表resultList,将不为null的链表连接到resultList即可。*/
ListNode dummy=new ListNode(-1);
ListNode resultList=dummy;
//说明小于链存在,将其连接到resultList上
if(head1.next!=null){
resultList.next=head1.next;
//非常关键点②:当前resultList指向的是head1链表的头结点,要使得head2能够连接到其尾部需要将resultList指针移动到head1尾部
while(head1.next!=null){
resultList=resultList.next;
head1=head1.next;
}
}
//说明等于链存在,将其连接到resultList上
if(head2.next!=null) {
resultList.next=head2.next;
while(head2.next!=null){
resultList=resultList.next;
head2=head2.next;
}
}
//说明大于链存在,将其连接到resultList上
return dummy.next;
}
}
相关文章推荐
- 数据结构与算法分析笔记与总结(java实现)--链表9:有序环形链表中插入新结点问题
- 数据结构与算法分析笔记与总结(java实现)--链表17:无环单链表判断是否相交问题
- 数据结构与算法分析笔记与总结(java实现)--链表4:单调链表合并问题
- 数据结构与算法分析笔记与总结(java实现)--链表2:倒数第k个结点问题(k从1开始)
- 数据结构与算法分析笔记与总结(java实现)--链表8:对排序链表删除重复结点问题
- 数据结构与算法分析笔记与总结(java实现)--链表16:单链表判断是否有环问题
- 数据结构与算法分析笔记与总结(java实现)--链表19:判断单链表是否相交问题
- 数据结构与算法分析笔记与总结(java实现)--链表14:删除链表中所有指定值结点问题
- 数据结构与算法分析笔记与总结(java实现)--链表问题面试笔试注意点
- 数据结构与算法分析笔记与总结(java实现)--链表6:两个链表找公共结点问题
- 数据结构与算法分析笔记与总结(java实现)--链表1:从尾到头打印链表值问题
- 数据结构与算法分析笔记与总结(java实现)--链表7:含环链表找环入口结点问题
- 数据结构与算法分析笔记与总结(java实现)--链表15:链表回文判断问题
- 数据结构与算法分析笔记与总结(java实现)--排序11:有序矩阵查找练习题
- 数据结构与算法分析笔记与总结(java实现)--数组11:数组中的逆序对(﹡)
- 数据结构与算法分析笔记与总结(java实现)--二叉树22:二叉搜索树与双向链表
- 数据结构与算法分析笔记与总结(java实现)--字符串11:合法括号序列判断练习题
- 数据结构与算法分析笔记与总结(java实现)--链表10:输入某个结点删除单向链表中的该结点
- 数据结构与算法分析笔记与总结(java实现)--数组7:判断单链表是否相交问题构建乘积数组
- 数据结构与算法分析笔记与总结(java实现)--字符串面试指南