Quick Selcet,O(n)的时间复杂度内找到无序数组中的第k大的数

Quick Select是快速排序的一种变形,它利用分隔数组策略在平均O(n)时间内找到无序数组的第k大元素。与快速排序不同的是,它避免了完整的递归过程,从而降低了时间复杂度。该方法常用于解决Kth Largest Element和寻找中位数等问题。在处理Median Of Two Sorted Array时,通过O(1)时间将问题规模减半,达到logn的时间复杂度。此外,它也适用于Majority Element问题,能够以O(n)时间找出出现次数超过一半的数字。
摘要由CSDN通过智能技术生成
  • Quick Select实质是快速排序算法中的一个步骤(找出未排序数组中的任意大的元素),其中用到了分隔数组的思想,默认的分隔条件是小于等于中间元素的在左边,大于的放在右边,这样将原问题分割一半,在确定的一半空间里寻找第k大的元素。Quick Select平均情况下的时间复杂度是O(n)。相关题目:Kth Largest Element,Median(当数组长度为奇数和偶数时,其中位数是不同的)等。

 

  • Kth Largest Element in an Array,最优解法。

 

                                

 

  • Quick Select与Quick Sort有许多相似之处,不同点在于图中画红框的部分,这里是用O(n)的时间将规模为n的问题减半,判断下一步是在哪个半区中寻找第k大的元素,这里排序是按降序排的。省去了快速排序中最后的递归过程,所以时间复杂度上有所优化。

 

  • 相似题目:Median Of Two Sorted Array,将规模为n的问题经过O(1)的时间复杂度转化成规模为n/2的问题,时间复杂度是logn(举例:在班级排名第10名,要想排名上升到第五名,可以把前五名弄走),这里要让k变成k/2,要么移除A中的前k/2

可以使用快速选择算法来解决这个问题,其时间复杂度为O(N)。 快速选择算法基于快速排序,但不需要完全排序整个数组。它通过每次选择一个基准元素并将数组分为两个部分来工作,然后根据基准元素的位置来确定我们需要搜索的那个部分。 具体地,我们可以首先随机选择一个元素作为基准元素,然后将数组中比该元素小的元素放在它的左边,比该元素大的元素放在它的右边。假设基准元素的位置为p,则左边的子数组中有p个元素小于它,右边的子数组中有n-p-1个元素大于它。如果k=p,则基准元素即为第k小的元素;如果k<p,则我们需要在左边的子数组中继续搜索第k小的元素;如果k>p,则我们需要在右边的子数组中继续搜索第k-p-1小的元素。 下面是使用快速选择算法求解第k小的的C代码: ``` #include <stdio.h> #include <stdlib.h> int partition(int* nums, int left, int right) { int pivot = nums[left]; int i = left + 1, j = right; while (i <= j) { while (i <= j && nums[i] < pivot) { i++; } while (i <= j && nums[j] >= pivot) { j--; } if (i < j) { int temp = nums[i]; nums[i] = nums[j]; nums[j] = temp; } } int temp = nums[left]; nums[left] = nums[j]; nums[j] = temp; return j; } int quickSelect(int* nums, int left, int right, int k) { if (left == right) { return nums[left]; } int pivotIndex = partition(nums, left, right); if (k == pivotIndex) { return nums[k]; } else if (k < pivotIndex) { return quickSelect(nums, left, pivotIndex - 1, k); } else { return quickSelect(nums, pivotIndex + 1, right, k); } } int findKthSmallest(int* nums, int size, int k) { return quickSelect(nums, 0, size - 1, k - 1); } int main() { int nums[] = {3, 2, 1, 5, 6, 4}; int size = sizeof(nums) / sizeof(int); int k = 2; int kthSmallest = findKthSmallest(nums, size, k); printf("The %dth smallest element is %d\n", k, kthSmallest); return 0; } ``` 在这个例子中,我们使用数组{3, 2, 1, 5, 6, 4}来演示如何找到第2小的元素。我们首先调用findKthSmallest函,并将nums数组的大小和k值作为参传递。在findKthSmallest函中,我们调用quickSelect函来实际查找第k小的元素。在quickSelect函中,我们首先将left和right参传递给partition函,以便将数组分为两个部分。然后,我们根据pivotIndex的值决定搜索哪个子数组。如果k等于pivotIndex,则我们找到了第k小的元素;否则,我们递归调用quickSelect函来搜索左边或右边的子数组。最后,我们在main函中打印出找到的第k小的元素。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值