查找 Kth 小的数

查找第k小数:


(1)境界一:全部排序 :O(n*lgn+k)


先快速排序O(n*lgn),然后在找出最小的k个数。O(k)


(2)境界二:部分排序 。O(kn)


根据选择排序,每次可以取得最小的数放在开头。
/*输入:数组array,及其长度length,k;
输出: 第k小的元素 :
*/
int selectTheKthSmallest(int *array,int length,int k){
int i,j,m;


for(i=0;i<k;i++){
m=i;


for(j=i+1;j<length;j++){
if(array[j]<array[m])
m=j;
}
if(m!=i){
swap(&array[i],&array[m]);
}


}


return array[k-1];
}


(3)境界三 : 计算排序O(n),然后选择第k个数。
空间复杂度O(range).


缺陷:各个元素需要是整形的,且元素的范围
需要时0~range.


(4)境界四:快速排序扩展:O(n*lgk)


elemType findKth(elemType* array ,int length ,int k);


思想:
对于数组s[0..n-1],首先用数组中的任意一个元素(可以取第一个)将数组分为三个部分:s[0..p-1], s[p], s[p+1..n-1],其中s[0..p-1]中的值都不大于s[p],s[p+1..n-1]中的值不小于s[p]。
如果p=K-1,则s[p]是要查找的元素,返回s[p]。
如果p<K-1,则第K小的元素一定在s[p+1..n-1]中,而且是s[p+1..n-1]中的第K-p-1小的元素,你可在这一段中查找第K-p-1大的元素即可。
注意:由于数组可以看作是静态指针,所以s[p+1..n-1]可以看作是以s+p+1指向的数组,你可以在C++中使用s+p+1来表示这个数组。


代码实现:


/*选择枢纽点,返回的总是array[0] */
elemType selectPivot(elemType* array, int length){



}


elemType findKth(elemType *array,int length ,int k){

int left=0;
int right=length-1;
int pivot=selectPivot( array, length);
while(left<right){
while(left<right && array[right]>=pivot)
right--;


array[left]=array[right];

while(left<right && array[left]< pivot )
left++;


array[right]=array[left];


}
array[left]=pivot;


if(left==k-1)
return array[left];


else if(left>k-1)
return findKth(array,left,k);


else 
return findKth(s+left+1,length-(left+1),k-(left+1));


}
### 查找组或列表中第 K 小的元素 为了查找组或列表中的第 K 小元素,可以采用多种方法。以下是几种常见的解决方案: #### 方法一:基于最小堆的方法 通过构建一个小根堆(也称为最小堆),可以在 O(n log k) 时间复杂度内解决问题。这种方法特别适合处理大据集。 ```python import heapq def find_kth_smallest_heap(nums, k): min_heap = [] for num in nums: heapq.heappush(min_heap, num) result = None for _ in range(k): result = heapq.heappop(min_heap) return result ``` 此代码片段展示了如何利用 Python 的 `heapq` 库创建并操作最小堆来获取第 K 小元素[^1]。 #### 方法二:使用快速选择算法 另一种高效的方式是应用快速选择算法,它是一种改进版的快速排序技术,平均情况下能在 O(n) 时间完成任务。该策略不需要完全对整个序列进行排序,而是仅需关注目标位置附近的子区间。 ```python from random import randint def partition(nums, low, high): pivot_index = randint(low, high) pivot_value = nums[pivot_index] # Move pivot to end nums[pivot_index], nums[high] = nums[high], nums[pivot_index] store_index = low for i in range(low, high): if nums[i] < pivot_value: nums[store_index], nums[i] = nums[i], nums[store_index] store_index += 1 # Place pivot after last element less than it. nums[store_index], nums[high] = nums[high], nums[store_index] return store_index def quick_select(nums, left, right, index): pos = partition(nums, left, right) if pos + 1 == index: return nums[pos] elif pos + 1 < index: return quick_select(nums, pos + 1, right, index) else: return quick_select(nums, left, pos - 1, index) def find_kth_smallest_quickselect(nums, k): n = len(nums) return quick_select(nums, 0, n-1, k) ``` 上述实现包含了完整的快速选择逻辑以及辅助函 `partition()` 来执行分割操作[^3]。 #### 方法三:简单排序取索引 对于较小规模的据集合或者当性能不是首要考虑因素时,可以直接先对据进行升序排列再取出对应下标的值作为结果。虽然这种方式效率较低,但在某些场景下仍然适用。 ```javascript var findKthSmallestSimpleSort = function(nums, k) { nums.sort((a,b) => a-b); return nums[k-1]; }; ``` 这段 JavaScript 代码实现了简单的全量排序方案,并返回所需的结果项[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值