騰訊算法崗一面算法題——計數排序
阿新 • • 發佈:2018-08-20
sort space oat ret light 函數 class 兩個 not
給定兩個整數數組,對第一個數組進行排序,整數順序由其在第二個數組中的位置決定。對於沒有出現在
第二個整數數組中的整數,應排在末尾,其之間的順序無限制。這裏整數的取值範圍是[0, 2 ^ 32 - 1]
例: 第一個整數數組為 5 1 6 2 1 2 3, 第二個整數數組為2 1 3, 則排序結果為2 2 1 1 3 6 5或2 2 1 1 3 5 6
這道題很明顯的第一個思路就是,先生成一個數到index下標的映射,然後建立一個compare函數,根據這個compare函數寫一個快排。
相關代碼如下:
# -*- coding:utf-8 -*- num2index = dict() def cmp(a, b): if a not in num2index and b not in num2index: return 0 elif a not in num2index: return 1 elif b not in num2index: return -1 else: if num2index[a] < num2index[b]: return -1 elif num2index[a] == num2index[b]: return 0 else: return 1 def quicksort(array, begin, end): # print array if end - begin <= 1: return elif end - begin == 2: if cmp(array[begin], array[begin + 1]) > 0: array[begin], array[begin + 1] = array[begin + 1], array[begin] return flag = array[begin] low = begin + 1 high = end - 1 while (low < high): while low < high and cmp(array[high], flag) > 0: high -= 1 while low < high and cmp(array[low], flag) <= 0: low += 1 if low != high: array[low], array[high] = array[high], array[low] if high == low == begin + 1: quicksort(array, begin + 1, end) else: array[begin], array[high] = array[high], array[begin] quicksort(array, begin, high) quicksort(array, high + 1, end) def func(list1, list2): global num2index for index, num in enumerate(list2): num2index[num] = index # sorted(list1, cmp=cmp) quicksort(list1, 0, len(list1)) print list1 if __name__ == "__main__": list1 = [5, 1, 6, 2, 1, 2, 3] list2 = [2, 1, 3] func(list1, list2)
這個代碼提交給面試官,面試官問了一下時間復雜度,顯然快排的時間復雜度是nlog(n),面試官讓我改成線性時間,o(╯□╰)o,抱歉當時那幾個線性排序的算法都不記得了,面試官提醒了一下用count sort ,當時想不起來了。
回去的時候才想了一下。純整數的排序,確實能夠利用空間換時間,得到線性的時間復雜度。先遍歷list1,建立一個num到count的映射,然後遍歷list2,直接每個數字出現了多少次就加幾個到結果中。同時把對應的count置為0,然後在遍歷一遍num2count,對應value不是0的,加入value個鍵值。最後返回result
# -*- coding:utf-8 -*- def func(list1, list2): num2count = dict() for num in list1: if num2count.has_key(num): num2count[num] += 1 else: num2count[num] = 1 result = [] for num in list2: for _ in range(num2count[num]): result.append(num) num2count[num] = 0 for num in num2count: if num2count[num] != 0: for _ in range(num2count[num]): result.append(num) print result if __name__ == "__main__": list1 = [5, 1, 6, 2, 1, 2, 3] list2 = [2, 1, 3] func(list1, list2)
後面又回去想了想,好像還可以繼續優化,第一遍利用快排的思想,把list1變成左邊是在list2中出現過的數,右邊是沒有出現過的數。於是右邊本來就是無序的,就可以直接對左邊部分進行count sort,這樣的代價才應該是最低的,無論從空間復雜性還是時間復雜性來說。
騰訊算法崗一面算法題——計數排序