其实不一定需要排序,采用类似快排的想法,随机挑选划分成三堆:比P小的、P、大等于P的。
然后判断P在当前子序列中的位置距离,其右侧有几个比它大的:
- k-1个比它大的,返回P即可;
- 比k-1个少,在左侧序列中到k-1-offset个即可。offset是当前比P大的个数。
- 比k-1个多,迭代右侧序列。
(详见代码,复杂度O(NlogN))
def find_k(arr, k):
def split(low, high, k=0):
if low >= high:
return arr[low]
i, j, p = low, high, low
while i < j:
while i < j and arr[j] >= arr[p]: # 找到右边第一个小的
j -= 1
while i < j and arr[i] <= arr[p]: # 找到左边第一个大的
i += 1
arr[i], arr[j] = arr[j], arr[i]
arr[p], arr[j] = arr[j], arr[p] # 把哨兵和最后一个找到的j对换
# split(low, i), split(i + 1, high) # 加上这行就是快排
offset = high-i # 比 arr[i]大的有offset位
if offset == k-1: # 右边有k位则当前即为第k大的
return arr[i]
elif offset < k-1:
return split(low, i-1, k-offset-1)
else:
return split(i+1, high, k)
return split(0, len(arr) - 1, k)
print(find_k(eval(input()), 3)) 
京公网安备 11010502036488号