https://leetcode.com/problems/kth-largest-element-in-an-array/

巧妙常考题。

这里参考http://www.cs.yale.edu/homes/aspnes/pinewiki/QuickSelect.html
O(n)算法。 quickselection algorithm。

思路就是随机选一个数作为pivot,然后新建list nums1, nums2,然后把大于pivot的数,(注意这里仅仅是大于)放到nums1里面,然后小于pivot的数放到nums2里面,这个时候我们就可以做一定的分析。

因为大于pivot的数有len(nums1)个,那么如果k <= len(nums1)的话,那么我们就可以再到nums1里面找第k大的数,缩小的问题规模。

原本我以为如果k >len(nums1) + 1, 就可以在nums2里面找(k - (len(nums1) + 1))。例如,比pivot大的有5个数,那么如果k == 7, 那么第6大的肯定是pivot,那么第7大的肯定就在nums2里面,然后在nums2里面找第7−6=1大的数就行。但是这里忽略了一个问题就是pivot的数目可能不止一个,所以这里的边界条件是 k >len(nums) - len(nums2).其余的情况就是返回pivot就行。

参考http://bookshadow.com/weblog/2015/05/23/leetcode-kth-largest-element-array/

import random

class Solution(object):
    def findKthLargest(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: int
        """
        pivot = random.choice(nums)
        nums1, nums2 = [], []
        for num in nums:
            if num > pivot:
                nums1.append(num)
            elif num < pivot:
                nums2.append(num)
        if k <= len(nums1):
            return self.findKthLargest(nums1, k)
        elif k > len(nums) - len(nums2):
            return self.findKthLargest(nums2, k - (len(nums) - len(nums2)))
        else:#等于pivot
            return pivot