首页 > 试题广场 >

查找第K大的元素

[编程题]查找第K大的元素
  • 热度指数:11207 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
给定一个无序的整型数组A[n],数组大小大于等于3,允许有值相同的元素;请设计算法找到该数组排序后第三大的元素值并输出.

输入描述:
一个非空的整数数组(至少有3个元素,可正可负)


输出描述:
第三大的元素值
示例1

输入

[1,2,3,4,5]

输出

3
示例2

输入

[1,1,2,2,3]

输出

2
示例3

输入

[6,5,4,4,1,2]

输出

4

我来给出这类题的通用解法,也就是求无序数组的第K大(或第K小)的问题,下面给出两种AC了的方法

import java.util.PriorityQueue;
import java.util.Scanner;
import static java.lang.Integer.parseInt;
import static java.lang.System.in;

public class Main{
    public static void main(String[] args) {
        Scanner sc = new Scanner(in);
        String[] str = sc.nextLine().replace("[", "").replace("]", "").split(",");
        int[] data = new int[str.length];
        for (int i = 0; i < data.length; i++) {
            data[i] = parseInt(str[i]);
        }
        System.out.println(findKthNum(data, 3));
        System.out.println(findKthNum1(data, 3));
    }
//方法1,基于快排思想的partion划分,时间复杂度O(n),空间复杂度O(1)
    public static int findKthNum(int[] data, int k) {
        int begin = 0, end = data.length - 1;
        int pos = 0;
        while (begin <= end) {
            pos = partion(data, begin, end);
            if (pos == k - 1) {
                return data[pos];
            } else if (pos > k - 1) {
                end = pos - 1;
            } else {
                begin = pos + 1;
            }
        }
        return -1;
    }

    private static int partion(int[] data, int begin, int end) {
        int temp = data[begin];
        while (begin < end) {
            while (begin < end && data[end] <= temp) {
                end--;
            }
            swap(data, begin, end);
            while (begin < end && data[begin] > temp) {
                begin++;
            }
            swap(data, begin, end);
        }
        return begin;
    }

    public static void swap(int[] arr, int i, int j) {
        if (arr == null || i >= arr.length || j >= arr.length || i < 0 || j < 0) {
            return;
        }
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
    //方法2,建小顶堆,时间复杂度O(n*logk),空间复杂度O(k)
    public static int findKthNum1(int data[], int k) {
        PriorityQueue<Integer> heap = new PriorityQueue<>();
        for (int item : data) {
            if (heap.size() < k) {
                heap.add(item);
            } else if (item > heap.peek()) {
                heap.poll();
                heap.add(item);
            }
        }
        return heap.poll();
    }
}
编辑于 2019-10-03 22:06:43 回复(0)
基于快排实现
填坑法:左边第一个元素作为参照值,并挖出来,空出位置;然后从右边往左找到第一个小于参照值的数填进来;此时右边空出一个位置;然后从左边找到一个大于参照值的数,填到右边的空位,此时左边空出一个位置......不断左右找数填坑,最终左右遍历坐标相等时的坑位就是参照值的位置。由 挖坑填数 排序得到的参照值的位置划分序列,分别进行左右递归;
import java.util.*;
public class Main {
    /*填坑法*/
    public static int getIndex(int[] arr,int left,int right){
        int pivot = arr[left];
        while(left<right){
            while(left<right&&arr[right]>=pivot){
                right--;
            }
            if(left<right){
                arr[left] = arr[right];
                left++;
            }
            while(left<right&&arr[left]<=pivot){
                left++;
            }
            if(left<right){
                arr[right] = arr[left];
                right--;
            }
        }
        if(left==right){
            arr[left] = pivot;
        }
        return left;
    }
    /*1.获取中轴点 index  2.中轴点左边递归 3.中轴点右边递归*/
    public static void quickSort(int[] arr,int start,int end){
        if(start<end){
            int index = getIndex(arr,start,end);
            quickSort(arr,start,index);
            quickSort(arr,index+1,end);
        } 
    }
    
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        String[] line = sc.nextLine().replace("[","").replace("]","").split(",");
        int[] arr = new int[line.length];
        for(int i = 0;i<line.length;i++){
            arr[i] = Integer.parseInt(line[i]);
        }
        //查找排序后第三大的元素
        /*
        Arrays.sort(arr);
        */
        quickSort(arr,0,arr.length-1);
        System.out.println(arr[arr.length -3]);
    }
}


发表于 2020-02-19 19:38:50 回复(0)
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
 
bool compare(const int &a,const int &b)
{
    return a>b;
}
 
int main()
{
    int num;
    vector<int> v;
    while(getchar()!=']')
    {
        cin>>num;
        v.push_back(num);
    }
    sort(v.begin(),v.end(),compare);
    cout<<v[2];
}

发表于 2020-02-18 10:31:37 回复(6)
#include<bits/stdc++.h> 
using namespace std; 
int main()
{
    vector<int> a;
    string s;
    cin >> s;
    int cur, sign = 1;
    for (int i = 1; i < s.length(); i++)
    {
        if (!isdigit(s[i]) && s[i] != '-')
        {
            a.push_back(cur * sign);
            cur = 0;
            sign = 1;
        }
        else if (isdigit(s[i]))
            cur = cur * 10 + s[i] - '0';
        else
            sign = -1;
    }
    sort(a.begin(),a.end());
    cout<<a[a.size()-3]<<endl;
    return 0;
}

发表于 2019-07-03 15:24:40 回复(0)
使用快排来求解这道题:
#include <vector>
#include <algorithm>
#include <iostream>

using namespace std;

int partition(vector<int>& arr, int low, int high) {
    swap(arr[low], arr[low + rand() % (high - low + 1)]);
    int pivot = arr[low];
    while (low < high) {
        while (low < high && arr[high] <= pivot) --high;
        if (low < high) arr[low++] = arr[high];
        while (low < high && arr[low] >= pivot) ++low;
        if (low < high) arr[high--] = arr[low];
    }
    arr[low] = pivot;
    return low;
}

int quickSort(vector<int>& arr, int low, int high) {
    if (low <= high) {
        int mid = partition(arr, low, high);
        if (mid == 2) {
            return arr[mid];
        } else if (mid > 2) {
            return quickSort(arr, low, mid - 1);
        } else {
            return quickSort(arr, mid + 1, high);
        }
    }
    return -1;
}

int findKth(vector<int>& arr) {
    int len = arr.size();
    return quickSort(arr, 0, len - 1);
}

int main() {
    int num;
    vector<int> arr;
    while (getchar() != ']') {
        cin >> num;
        arr.emplace_back(num);
    }
    cout << findKth(arr);
}

发表于 2021-03-30 17:40:03 回复(0)
对不起,我只用了两行代码。
import java.util.Arrays;
import java.util.Scanner;
 
public class Main{
     public static int getThirdest(int[] nums){
         Arrays.sort(nums);
          return nums[nums.length-3];
      }
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String temp = in.nextLine();
        String res = temp.substring(1,temp.length()-1);
        String[] str = res.trim().split(",");
        int len = str.length;
        int[] num = new int[len];
        for (int i=0;i<len;i++){
            num[i] = Integer.parseInt(str[i]);
        }
        System.out.println(getThirdest(num));
    }
}


发表于 2020-10-12 09:22:21 回复(0)
py之能一行绝不两行
print(sorted(map(int,eval(input())))[-3])

发表于 2020-03-16 15:30:22 回复(1)
JavaScript(Node) 😎题目:有赞👍-查找第k大元素(sort)
const readline = require('readline')
const rl = readline.createInterface({
    input: process.stdin,
    ouput: process.stdout
})
let inArr = []
rl.on('line',line=>{
    if(!line) return
    inArr.push(line.trim())
    if(inArr.length === 1){
        let a = inArr[0]
        a = JSON.parse(a)
        a.sort((a,b) => b-a)
        console.log(a[2])
    }
})


发表于 2020-03-01 17:54:27 回复(0)
#include <bits/stdc++.h>
using namespace std;

int main(){
    vector<int> a;
    string s;
    cin>>s;
    stringstream ss(s);
    int x;
    char c;
    while(ss>>c){
        if(c==']')
            break;
        ss>>x;
        a.push_back(x);
    }
    priority_queue<int, vector<int>, greater<int>> q;
    for(int i=0;i<a.size();i++){
        if(q.size()<3)
            q.push(a[i]);
        else{
            if(a[i]>q.top()){
                q.pop();
                q.push(a[i]);
            }
        }
    }
    cout<<q.top()<<endl;
    return 0;
}

发表于 2019-11-30 01:08:57 回复(0)
冒泡思想pop三趟就行。
不知道今天牛客怎么了,后台一直出错,自己在本地都可以AC。
#include<iostream>
#include<vector>
using namespace std;

int main()
{
    vector<int> input;
    int tmp;
    while(cin>>tmp)
    {
        input.push_back(tmp);
        if(cin.get()=='\n')
            break;
    }
    int n=input.size();
    for(int i=0;i<3;i++)
    {
        for(int j=0;j<n-i-1;j++)
        {
            if(input[j]>input[j+1])
            {
                tmp=input[j+1];
                input[j+1]=input[j];
                input[j]=tmp;
            }
        }
    }
    cout<<input[n-3];
}

发表于 2019-10-15 19:01:48 回复(0)
#include <bits/stdc++.h>
using namespace std;
int mypartition(vector<int> &arr,int start,int end,int k){
    int left=start,right=end;
    int p=arr[left];
    if(start<end){
        while(left<right){
            while(left<right&&arr[right]<=p)
                right--;
            arr[left]=arr[right];
            while(left<right&&arr[left]>=p)
                left++;
            arr[right]=arr[left];
        }
        arr[left]=p;
        if(left==k)
            return arr[k];
        else if(left>k)
            return mypartition(arr,start,left-1,k);
        else
            return mypartition(arr,left+1,end,k);
    }
}
int main(){
    vector<int> arr(1,0);
    cin.ignore();
    while(1){
        int t;
        cin>>t;
        arr.push_back(t);
        if(cin.get()==']')
            break;
    }
    int ans=mypartition(arr,1,arr.size()-1,3);
    cout<<ans;
    return 0;
}

发表于 2019-10-14 20:39:39 回复(0)
#include <vector>
#include <queue>
#include <iostream>
#include <string>
using namespace std;

//c++ priority_queue
//使用优先队列

int main(){
    vector<int> arr;
    string is;
    getline(cin, is);
    int start = 1;
    int end = is.find_first_of(',');
    string tempStr;
    while (end != string::npos){
        tempStr = is.substr(start, end - start);
        arr.push_back(atoi(tempStr.c_str()));
        start = end + 1;
        end = is.find_first_of(',', end + 1);
    }
    tempStr = is.substr(start, end - start - 1);
    arr.push_back(atoi(tempStr.c_str()));

    priority_queue<int, vector<int>, greater<int>> p;//小顶堆
    for (auto val : arr){
        if (p.size() < 3){
            p.push(val);
        }
        else {
            if (val > p.top()){
                p.pop();
                p.push(val);
            }
        }
    }
    cout << p.top();
    return 0;
}

发表于 2019-08-21 14:56:37 回复(0)
基于快速排序的方法
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String[] strings = in.nextLine().replace("[","").
                replace("]","").split(",");
        int[] a = new int[strings.length];
        int n = a.length;
        for (int i=0;i<n;i++)
            a[i] = Integer.parseInt(strings[i]);
        int k = n-3;
        int t = -1;
        int low = 0,high = n-1;
        while (t != k){
            t = partition(a,low,high);
            if (t > k)
                high = t-1;
            else if (t < k)
                low = t+1;
        }
        System.out.println(a[t]);
    }

    public static int partition(int[] a,int low,int high){
        int key = a[low];
        while (low < high){
            while (low < high && key <= a[high])
                high--;
            if (low < high)
                a[low++] = a[high];
            while (low < high && a[low] <= key)
                low++;
            if (low < high)
                a[high--] = a[low];
        }
        a[low] = key;
        return low;
    }
}
在k已确定,且k并不是很大时,可以用这种方法,只需一次遍历
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String[] strings = in.nextLine().replace("[","").
                replace("]","").split(",");
        int[] a = new int[strings.length];
        int n = a.length;
        for (int i=0;i<n;i++)
            a[i] = Integer.parseInt(strings[i]);
        int first = Integer.MIN_VALUE;
        int second = Integer.MIN_VALUE;
        int third = Integer.MIN_VALUE;
        for (int i=0;i<n;i++){
            if (a[i] > first){
                third = second;
                second = first;
                first = a[i];
            }else if (a[i] > second){
                third = second;
                second = a[i];
            }else if (a[i] > third){
                third = a[i];
            }
        }
        System.out.println(third);
    }
}



发表于 2019-08-15 16:30:10 回复(0)
#快速排序中的一步,前面小,后面大
def partition(array):
    if len(array) == 1:
        return 0
    low = 0
    high = len(array) - 1
    key = array[0]
    while low < high:
        while low < high and  key >= array[high]:
            high -= 1
        array[low] = array[high]
        while low < high and array[low] >= key:
            low += 1
        array[high] = array[low]
    array[low] = key
    return low

#查找数组的第K大的数
def find_topK(array,k):
    #快速排序中的一步
    index = partition(array)
    #找到第k个,直接返回
    if index + 1 == k:
        return array[index]
    #找到的位置大于k,在数组前index部分再找k
    elif index + 1 > k:
        return find_topK(array[:index],k)
    #找到的位置小于k,在数组的后index位置找k-index
    else:
        return find_topK(array[index+1:],k-index-1)


list = [int(x) for x in input()[1:-1].split(",")]
num = find_topK(list,3)
print(num)
发表于 2019-08-14 11:33:32 回复(0)
""""
求第k大值
"""

if __name__ == "__main__":
    a = eval(input().strip())
    print(sorted(a)[-3])

发表于 2019-07-12 13:09:17 回复(1)
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <sstream>

using namespace std;

int main() {
    string input,tmp;
    while (cin>>input) {
        vector<int> array;
        input.erase(input.end() - 1);
        input.erase(input.begin());
        stringstream inputline(input);
        while(getline(inputline, tmp, ',')) {
            auto v = stoi(tmp);
            array.push_back(v);
        }
        sort(array.begin(),array.end());
        cout<<array[array.size() - 3]<<endl;
    }
    return 0;
}

发表于 2019-01-08 19:56:37 回复(0)
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String str = scanner.next();
        String[] strNumber = str.substring(1, str.length() - 1).split(",");
        int[] number = new int[strNumber.length];
        for (int i = 0; i < strNumber.length; i++) {
            number[i] = Integer.parseInt(strNumber[i]);
        }
        Arrays.sort(number);
        System.out.println(number[number.length -3]);
    }
}
发表于 2019-07-04 17:39:36 回复(0)
只需要用三个变量存取前三大的值,在输入过程中不断更新即可
#include<iostream>
#include<cstdio>
#include<limits.h>
using namespace std;

int main()
{
    int x=INT_MIN,y=INT_MIN,z=INT_MIN;//x第一大,y第二大,z第三大
    int k;
    while(getchar()!=']')
    {
        cin>>k;
        if(k>=x)
        {
            z=y;    y=x;    x=k;
        }
        else if(k>=y)
        {
            z=y;    y=k;
        }
        else if(k>=z)
        {
            z=k;
        }
        else
            continue;
    }
    cout<<z<<endl;
    return 0;
}


发表于 2021-01-30 10:40:04 回复(0)
import java.util.Scanner;
import java.util.Arrays;
public class Main{
    public static void main(String[] args){
        Scanner input=new Scanner(System.in);
        String[] str=input.nextLine().replace("[","").replace("]","").split(",");
        int strInt[]=new int[str.length];
        for(int i=0;i<str.length;i++){
            strInt[i]=Integer.parseInt(str[i]);
        }
        Arrays.sort(strInt);
        System.out.println(strInt[strInt.length-3]);
    }
}
利用Arrays类的sort方法轻松解决
发表于 2020-03-18 15:52:28 回复(2)
import sys

c = input()[1:-1].split(',')
a = [int(i) for i in c]
a.sort(reverse= True)
print(a[2])
发表于 2024-05-09 15:56:09 回复(0)