求第k小算法
也就是快速选择算法,看到一个博客很详细分享一下地址:
快速选择算法实现
求第k大算法
c++实现方式
代码1
#include "stdio.h"
#include <vector>
#include <iostream>
using namespace std;
int findPos(vector<int>& arr, int left, int right)
{
int flag = arr[left];
while(left<right)
{
while(left<right&&arr[right]>=flag)
right--;
arr[left] = arr[right];
while(left<right&&arr[left]<flag)
left++;
arr[right] = arr[left];
}
arr[left] = flag;
return left;
}
int main()
{
vector<int> arr;
int ele;
while(cin>>ele)
{
arr.push_back(ele);
if(getchar() == '\n')
break;
}
int k;
cin>>k;
k = arr.size()-k+1;
k--;
int begin = 0, end= arr.size()-1;
int pos = 0;
while(begin<end)
{
pos = findPos(arr, begin, end);
if(pos == k)
break;
else
{
if(pos>k)
end = pos-1;
else
begin = pos + 1;
}
}
cout<<arr[k]<<endl;
return 0;
}
代码2
#include <iostream>
#include <algorithm>
using namespace std;
bool cmp(int a, int b){
return a > b;
}
int main(){
int num[10010], n, i = 0, k;
while(cin >> n)
num[i++] = n;
k = num[i-1];
num[i-1] = -1;/*让原本k位置的数变成一个足够小的数,使其在从大到小排序中,永远是最小的
//那个,这样不至于影响前面的排列*/
sort(num, num+i, cmp);
cout << num[k-1];
}
java实现方式
代码1 快排思想
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String[] firstLine = sc.nextLine().split(" ");
int[] arr = new int[firstLine.length];
for (int i = 0; i < arr.length; i++) {
arr[i] = Integer.parseInt(firstLine[i]);
}
int k = sc.nextInt();
System.out.println(findKMax(arr, 0, arr.length - 1, k - 1));
}
private static int findKMax(int[] arr, int left, int right, int k) {
int p = partition(arr, left, right);
if (p == k)
return arr[p];
else if (p < k)
return findKMax(arr, p + 1, right, k);
else
return findKMax(arr, left, p - 1, k);
}
private static int partition(int[] arr, int left, int right) {
int value = arr[left];
int p = left;
for (int i = left + 1; i <= right; i++) {
if (arr[i] > value) {
p ++;
swap(arr, p, i);
}
}
swap(arr, left, p);
return p;
}
private static void swap(int[] arr, int a, int b) {
int t = arr[a];
arr[a] = arr[b];
arr[b] = t;
}
}
代码2
import java.util.Scanner;
/**
* 类似与求第k小的问题
* 求第k大相当于求第n-k+1小,n为数组长度
*
* 著名的BFPRT算法可保证在线性时间内得到结果。
* https://blog.csdn.net/qq_32767041/article/details/86099117
*
* 这里使用快速选择算法,这是一种基于快速排序的算法,
* 在实现上比BFPRT更简单。
* https://blog.csdn.net/qq_32767041/article/details/86300744
*
* @author wylu
*/
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
String[] strs = scanner.nextLine().split(" ");
int[] arr = new int[strs.length];
for (int i = 0; i < arr.length; i++) {
arr[i] = Integer.valueOf(strs[i]);
}
int k = scanner.nextInt();
System.out.println(arr[quickSelect(arr, arr.length - k + 1)]);
}
}
/**
* 查找第k小元素
* @param arr 无序数组
* @param k 目标第k小
* @return 成功:返回第k小元素的索引
* 失败:返回-1
*/
public static int quickSelect(int[] arr, int k) {
int left = 0, right = arr.length - 1, idx;
while (left <= right) {
idx = partition(arr, left, right);
if ((k - 1) == idx) return idx;
else if ((k - 1) > idx) left = idx + 1;
else right = idx - 1;
}
return -1;
}
/**
* 对给定的数组区间进行划分
* @param arr 数组
* @param left 区间下限,包含arr[left]
* @param right 区间上限,包含arr[right]
* @return 返回划分后,划分基准的索引
*/
private static int partition(int[] arr, int left, int right) {
int j = left - 1;
for (int i = left; i < right; i++) {
if (arr[i] <= arr[right]) swap(arr, i, ++j);
}
swap(arr, ++j, right);
return j;
}
private static void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
代码3
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
List<Integer> list=new ArrayList<>();
while(sc.hasNext()){
list.add(sc.nextInt());
}
int n=list.get(list.size()-1);
list.remove(list.size()-1);
list.sort(new Comparator<Integer>(){
public int compare(Integer i2,Integer i1){
return i1-i2;
}
});
System.out.println(list.get(n-1));
}
}
Python3实现方式
代码:
print(sorted(map(int, input().split()))[-int(input())])