📌  相关文章
📜  通过从随机索引反转子数组形成的排序数组中的第 K 个最小元素(1)

📅  最后修改于: 2023-12-03 14:58:03.975000             🧑  作者: Mango

通过从随机索引反转子数组形成的排序数组中的第 K 个最小元素

介绍

给定一个长度为 n 的数组 nums,你需要通过多次交换一对随机索引的元素来对数组进行排序。现在你需要找到排序后的第 k 个最小元素。

例如,给定 nums = [1,3,4,2,5],通过交换索引为 2 和 3 的元素可以得到排序后的数组 [1,2,4,3,5]。第 k 个最小元素是 4。

解法

本题可以利用快速排序的思想来解决,对于快速排序而言,我们并不关心每次交换后的位置,而只关心该位置上的值和其他值的大小关系。因此,我们可以通过随机索引来打乱数组,然后使用快速排序的方法进行排序,最后找到第 k 小的元素。

具体做法如下:

  1. 选定一个随机索引 pivot,并以该索引的值为 pivot。随机选择一个索引 i 并将数组中的 pivotnums[i] 互换位置,这样 pivot 将被置于正确的位置上。
  2. 遍历数组,将小于 pivot 的元素放到左边,大于等于 pivot 的元素放到右边。同时,统计左边元素的个数 left_cnt
  3. 如果 left_cnt = k-1,则 pivot 即为结果;如果 left_cnt < k-1,则在右边继续查找第 k-left_cnt-1 个最小元素;如果 left_cnt > k-1,则在左边继续查找第 k 个最小元素。
  4. 重复步骤 1-3 直到找到第 k 个最小元素。

代码如下:

class Solution:
    def findKthLargest(self, nums: List[int], k: int) -> int:
        self.shuffle(nums)
        return self.quick_select(nums, 0, len(nums)-1, k)

    def shuffle(self, nums: List[int]) -> None:
        n = len(nums)
        for i in range(n):
            j = random.randint(i, n-1)
            nums[i], nums[j] = nums[j], nums[i]

    def partition(self, nums: List[int], left: int, right: int) -> int:
        pivot = nums[left]
        i, j = left, right
        while i < j:
            while i < j and nums[j] >= pivot:
                j -= 1
            nums[i] = nums[j]
            while i < j and nums[i] < pivot:
                i += 1
            nums[j] = nums[i]
        nums[i] = pivot
        return i

    def quick_select(self, nums: List[int], left: int, right: int, k: int) -> int:
        if left == right:
            return nums[left]
        p = self.partition(nums, left, right)
        left_cnt = p - left + 1
        if left_cnt == k:
            return nums[p]
        elif left_cnt < k:
            return self.quick_select(nums, p+1, right, k-left_cnt)
        else:
            return self.quick_select(nums, left, p-1, k)
时间复杂度

快速选择算法的平均时间复杂度为 $O(n)$,最坏时间复杂度为 $O(n^2)$。其中最坏情况发生在每次选到的 pivot 都是数组中的最大/最小元素的情况下,可以通过随机选择 pivot 来避免。因此,本算法的期望时间复杂度为 $O(n)$,空间复杂度为 $O(1)$。