线性时间找第k小

来源:互联网 发布:js push 数组对象 编辑:程序博客网 时间:2024/05/24 00:13

一个parition函数,就是快排里边的划分函数,思路就是找到一个枢轴元素,把小于等于它的放在它左边,大于它的放在右边,然后返回这个枢轴元素的位置下标。

一个q_select函数,用来找第k小。基本思路就是先用partition划分一次,划分成两部分,如果k小于等于左半部分的数的个数,就在左边找第k小,如果大于左半部分个数,就在右边找第(k-左半部分个数)。

这里注意的问题就是有重复元素。由于最终可能不会出现只剩一个元素的情况(剩下了一堆相等的数),所以当左右边界相等的时候,说明这一段数字都是相等的,也可直接返回。

#include <stdio.h>#include <iostream>#include <algorithm>#include <stdlib.h>using namespace std;int partition(int a[], int l, int r){int x = a[l];int i = l, j = r+1;while(1){while(a[++i] <= x && i < r);//一定是小于等于 (有重复元素都放在左边) while(a[--j] > x);if(i >= j)    break;swap(a[i], a[j]);}a[l] = a[j];a[j] = x;return j;}int q_select(int a[], int l, int r, int k){if(l == r || a[l] == a[r])//当把所有相等元素归在一起时,若边界值相等,则说明这一段数据都是相等的     return a[l];int i = partition(a, l, r);int j = i - l + 1;if(k <= j)    return q_select(a, l, i, k);else    return q_select(a, i+1, r, k-j);}int main(){int n, i, a[100005], k;scanf("%d", &n);for(i = 0 ; i < n ; i++){scanf("%d", &a[i]);}scanf("%d", &k);printf("%d\n", q_select(a, 0, n-1, k));return 0;}


0 0
原创粉丝点击