# slicing defmerge_sort(array):iflen(array)==0orlen(array)==1:return array mid =len(array)/2 left =merge_sort(array[:middle])#O(n) space due to slicing right =merge_sort(array[middle:])#O(n) space due to slicingreturnmerge(left, right)#调用一次merge是O(n)Time,在这里调用了logn次
时间复杂度
Upper Half to split: Time O(n)=1+2+4+...n/2
Lower Half to merge: Time O(nlogn) 每一层merge的时间复杂度是O(n) 一共有h=logn层
Total Time Complexity O(nlogn)
randrange (start, stop, step) doesn’t consider the last item i.e. it is exclusive. For example, randrange (10,20,1) will return any random number from 10 to 19 (exclusive). it will never select 20.
Time: Best Case and On average, both O(nlogn)
为什么Average是O(nlogn)
下面这个推导的最后结论
Space: O(logn) worst case O(n) 这次是只取决于高度了,因为每层的call stack上只分配了常数级别的空间(pivot_index)
classSolution(object):defrainbowSortII(self,array):""" input: int[] array return: int[] """# write your solution herereturn self.quickSort(array, 0, len(array) -1)defquickSort(self,A,start,end):if start >= end:return A left, right = start, end# key point 1: pivot is the value, not the index pivot = A[(start + end) //2];# key point 2: every time you compare left & right, it should be# left <= right not left < rightwhile left <= right:while left <= right and A[left]<= pivot: left +=1while left <= right and A[right]> pivot: right -=1if left <= right: A[left], A[right]= A[right], A[left] left +=1 right -=1 self.quickSort(A, start, right) self.quickSort(A, left, end)return A
III K种颜色,用quick sort的思想
传入两个区间,一个是颜色区间 color_from, color_to。另外一个是待排序的数组区间 index_from, index_to.
找到颜色区间的中点,将数组范围内进行 partition,<= color 的去左边,>color 的去右边。
然后继续递归。
时间复杂度 O(nlogk)n是数的个数, k 是颜色数目。这是基于比较的算法的最优时间复杂度。
不基于比较的话,可以用计数排序(Counting Sort)
classSolution(object):defrainbowSortIII(self,array,k):""" input: int[] array, int k return: int[] """# write your solution hereifnot array orlen(array)<=1:return arrayreturn self.sort(array, 0, len(array)-1,1,k)defsort(self,array,idx_l,idx_r,color_l,color_r):if idx_l==idx_r or color_l==color_r:return pivot=(color_l+color_r)//2 left, right = idx_l, idx_rwhile left<=right:while left<=right and array[left]<=pivot: left+=1while left<=right and array[right]>pivot: right-=1if left<=right: array[left],array[right]=array[right],array[left] left+=1 right-=1 self.sort(array,idx_l,right,color_l,pivot) self.sort(array,left,idx_r,pivot+1,color_r)return array
面试题目:
为什么基于比较的排序 时间复杂度下界是Omega(nlogn)
Given n numbers, there are n! possible permutations. For any value, x!=y, x<y is half of the permutation. In each comparison, we are left with n!/2 permutation. In the end, we operate log(n!) to achieve sorting.
Olog(n!)=O(nlogn) (Stirling Formula)
如果有1Mb的数据,用哪个sorting algorithm? What about 10Mb,100Mb,1Gb,1Tb,1Pb?
1Mb: Memory sorting 随便算法
1Tb: Disk sorting, External Sorting 外排,单机,多机,最后merge,写回磁盘
For any pivot position i;i∈{0,…,n−1}⋅ Time for partitioning an array : cn⋅ The head and tail subarrays contain i and n−1−i items, respectively: T(n)=cn+T(i)+T(n−1−i) Average running time for sorting (a more complex recurrence): T(n)=n1∑i=0n−1(T(i)+T(n−1−i)+cn)
最坏的情况不取决于input本身是否有序,而是取决于每次的pivot都选的特别差,比如每次都选到了最大的或者最小的,导致每一次都是n-1比它小,这就成了一个直上直下的一叉树,每一层都需要做n次交换,高度是n, worst case O( n2 )
Soln3: QuickSort Average O(n) Worst Case O(n2)
Time complexity: T(n) Let nT(n) Space complexity: O(1)=T(n/2)+O(n)=T(n/4)+O(n/2+n)=…=T(n/2nk)+O(n+n/2+…+n/2∧k)]=T(n/2nk)+O(n+2∗(1−0.5∧k))=2∧k=T(1)+O(2n−2)⇒T(n)=O(n)