将单向链表按某值划分成左边小、 中间相等、 右边大的形式-python3
2019-01-02 21:54
288 查看
基础解:荷兰国旗问题(笔试时可用,简单直接,但不稳定)
将所有的节点遍历得到链表的长度,再遍历一次将所有节点放置到一个数组中,对这个数组进行partition调整(荷兰国旗问题),再将每个数组中每个节点串起来即可。
进阶解:按照原链表各个节点的对应顺序将链表调整成三部分,小于num的、等于num的,大于num的,之后再将三个连起来即可。
代码如下:
[code]#coding=utf-8 ''' 将单向链表按某值划分成左边小、 中间相等、 右边大的形式 【 题目】 给定一个单向链表的头节点head, 节点的值类型是整型, 再给定一个 整 数pivot。 实现一个调整链表的函数, 将链表调整为左部分都是值小于 pivot 的节点, 中间部分都是值等于pivot的节点, 右部分都是值大于 pivot的节点。 除这个要求外, 对调整后的节点顺序没有更多的要求。 例如: 链表9->0->4->5- >1, pivot=3。 调整后链表可以是1->0->4->9->5, 也可以是0->1->9->5->4。 总 之, 满 足左部分都是小于3的节点, 中间部分都是等于3的节点(本例中这个部 分为空) , 右部分都是大于3的节点即可。 对某部分内部的节点顺序不做 要求。 进阶: 在原问题的要求之上再增加如下两个要求。 在左、 中、 右三个部分的内部也做顺序要求, 要求每部分里的节点从左 到右的 顺序与原链表中节点的先后次序一致。 例如: 链表9->0->4->5->1, pivot=3。 调整后的链表是0->1->9->4->5。 在满足原问题要求的同时, 左部分节点从左到 右为0、 1。 在原链表中也 是先出现0, 后出现1; 中间部分在本例中为空, 不再 讨论;右部分节点 从左到右为9、 4、 5。 在原链表中也是先出现9,然后出现4, 最后出现5。 如果链表长度为N,时间复杂度请达到O(N),额外空间复杂度请达到O(1)。 ''' class Node(object): """单向链表的结点""" def __init__(self,elem): self.elem=elem self.next=None class SingleLinkList(object): """单链表""" def __init__(self,node=None): """构造函数""" self.__head=node #头节点 def getHead(self): return self.__head def travel(self): """遍历链表""" cur=self.__head while cur!=None: print(cur.elem,end=" ") cur=cur.next print("") def add(self,item): """链表头部添加元素 O(1) """ node=Node(item) node.next=self.__head self.__head=node def listPartition1(self,num):#这种方法最快,但做不到稳定性,数组需要额外空间。 #普通问题 #时间复杂度是 O(N),空间复杂度是 O(N) #首先遍历一遍链表,得到链表的长度,将链表元素依次放到数组中,然后利用类似于快速排序中的partition 思想进行分割 #partition完之后再串成链表 if self.__head is None: #空链表 return self.__head cur=self.__head i=0 while cur: #遍历一次链表,统计元素个数即链表长度 cur=cur.next i+=1 #将链表中的每个元素依次放入到数组中 nodeArr=[] cur=self.__head for j in range(0,i): nodeArr.append(cur) cur=cur.next # print(i) #进行类似快速排序的partition nodeArr=self.arrPartition(nodeArr,num) #重新连接各个链表节点 for q in range(1,i): nodeArr[q-1].next=nodeArr[q] nodeArr[i-1].next=None return nodeArr def arrPartition(self,nodeArr,num): left=-1 right=len(nodeArr) index=0 while index<right: if nodeArr[index].elem<num: left += 1 nodeArr[left],nodeArr[index]=nodeArr[index],nodeArr[left] #交换 index+=1 elif nodeArr[index].elem==num: index+=1 else: right -= 1 nodeArr[right], nodeArr[index] = nodeArr[index], nodeArr[right] ##交换 return nodeArr def listPartition2(self,num):#测试通过 ''' * 进阶问题: 保证各部分内部的顺序与原来链表中各个节点的顺序相同 * 时间复杂度是 O(N),空间复杂度是 O(1) * 考察 利用有限的几个变量来调整链表的代码实现能力。 1.将链表分为三部分:small,equal,more small:2->1->null equal:5->5->null more:9->7->8->null 2.将small、equal、more三个链表重新串起来 3.整个过程需要特别注意对null节点的判断和处理 ''' less=Node(None) endless=Node(None) equal=Node(None) endequal=Node(None) more=Node(None) endmore=Node(None) #every node distributed to three lists while self.__head: Next=self.__head.next self.__head.next=None if self.__head.elem<num: if less.elem is None: less=self.__head endless=self.__head else: endless.next=self.__head endless=endless.next elif self.__head.elem==num: if equal.elem is None: equal=self.__head endequal=self.__head else: endequal.next=self.__head endequal=self.__head elif self.__head.elem>num: if more.elem is None: more =self.__head endmore=self.__head else: endmore.next=self.__head endmore=self.__head self.__head=Next # small and equal reconnect if endless.elem and equal.elem: endless.next=equal endequal=endequal if endequal.elem else endless # all reconnect if endequal.elem: endequal.next=more endmore=endmore if endmore.elem else endequal res=equal if equal.elem else more res=less if less.elem else res #返回链表头节点 return res def printLinkedList(self,node): print("Linked List:") while node.next: print(node.elem,end=" ") node=node.next print(node.elem) print("") if __name__=="__main__": s1 = SingleLinkList() s1.add(7) s1.add(9) s1.add(1) s1.add(8) s1.add(3) s1.add(5) s1.add(2) s1.add(5) s1.add(5) s1.add(4) s1.add(3) s1.travel() # res=s1.listPartition1(5) # s1.printLinkedList(res[0]) res=s1.listPartition2(6) #bug:如果没有等于num的链表就断掉了 s1.printLinkedList(res)
运行结果如下:
等程序无bug再粘
相关文章推荐
- 将单向链表按某个值划分成左边小、中间相等、右边大的形式 Python 版
- Java——将单向链表按某值划分成左边小、中间相等、右边大的形式(基础问题)
- 将单向链表按某值划分成左边小、中间相等、右边大的形式
- 链表问题---将单向链表按某值划分成左边小,中间相等,右边大的形式
- 将单向链表按某值划分成左边小、中间相等、右边大的形式
- 将单向链表按某值划分成左边小、中间相等、右边大的形式
- 算法总结之 将单向链表按某值划分成左边小、中间相等、右边大的形式
- 将单向链表按某值划分成左边小、 中间相等、 右边大的形式~迎娶是挺
- 将单向链表按某值划分成左边小、中间相等、右边大的形式(O(1)空间复杂度,稳定划分)
- [链表] - 将单向链表按某值划分成左边小、中间相等、右边大的形式
- Java——将单向链表按某值划分成左边小、中间相等、右边大的形式(进阶问题)
- 将单向链表按某值划分成左边小,中间相等,右边大
- 把单链表按某值划分成左边小,中间相等,右边大的形式,时间O(n),空间O(1)
- C++将链表划分为左边小,中间等,右边大于pivotKey的形式
- [JS]链表划分给定中间值,小的在左边,大的在右边并保持原排序
- [JS]链表划分给定中间值,小的在左边,大的在右边并保持原排序
- C++链表划分左边小中间等右边大 时间复杂度O(n) 空间复杂度O(1)
- 面试题12 在一个单向链表中 指定一个元素 x 然后将所有小于 x 的元素都放到 x 左边 剩下的元素放到 x 的右边
- 划分一个整形数组,把负数放在左边,零放在中间,正数放在右边
- 数据结构之链表面试题汇总(一)--查找单向链表的中间节点、倒数第K个节点