第k小个数和第k大个数,5种方法,速看!!!

36 篇文章 3 订阅
9 篇文章 0 订阅

1.第k小个数

地址:链接地址

1.1时间复杂度O(n)

1.1.1基于快排实现

将k值当做物理地址的值,比如第5个数其实就是数组4的位置,第2个数就是数组1的位置

每次只需要判断k在左区间还是右区间,一直递归查找k所在区间
最后只剩一个数时,只会有数组[k]一个数,返回数组[k]的值就是答案


描述
将k值当做物理地址的值,比如第5个数其实就是数组4的位置,第2个数就是数组1的位置

每次只需要判断k在左区间还是右区间,一直递归查找k所在区间
最后只剩一个数时,只会有数组[k]一个数,返回数组[k]的值就是答案

import java.util.Scanner;

public class Main{
    static int N = 100010;
    static int[] A = new int[N];
    static int n, k;
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        k = sc.nextInt();
        for(int i = 0; i < n; i++) A[i] = sc.nextInt();

        System.out.println(quickSort(0, n-1, k-1));
    }

    public static int quickSort(int l, int r, int k){
        if(l >= r) return A[k];

        int x = A[l], i = l-1, j = r+1;
        while(i < j) {
            do i++; while(A[i] < x);
            do j--; while(A[j] > x);
            if(i < j) {
                int temp = A[i];
                A[i] = A[j];
                A[j] = temp;
            }
        }

        if(k <= j) return quickSort(l, j, k);
        else return quickSort(j+1, r, k);
    }
}

1.2时间复杂度O(nlogn)

1.2.1快排后找到第k小的数

import java.util.*;
class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int k = sc.nextInt();
        int[] arr = new int[n];
        for(int i = 0; i < n; i++){
            arr[i] = sc.nextInt();
        }
        quickSort(arr,0,n-1);
       
        System.out.print(arr[k-1]);
       
    }
    static void quickSort(int[] arr,int l,int r){
        if(l>=r){
            return;
        }
        int i = l-1;
        int j = r+1;
        int mid = arr[(l+r)/2];
        while(i<j){
            do{
                i++;
            }while(arr[i]<mid);
            do{
                j--;
            }while(arr[j]>mid);
            if(i<j){
                int tmp = arr[i];
                arr[i] = arr[j];
                arr[j] = tmp;
            }
        }
        quickSort(arr,l,j);
        quickSort(arr,j+1,r);
    }
}

1.2.2 数组模拟堆来实现

import java.util.*;
//把整个数组建成堆,每次输出堆顶即可
//因此只需要用到输出集合的最小值
//还有删除最小值,关键是实现down操作。
//求最小值是o1的时间复杂度,而求插入和删除的时间复杂度与树的高度有关因此是logn的
class Main{
    static int m,n,size;
    static int[] p = new int[100010];
    public static void main(String [] args){
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        m = sc.nextInt();
        for(int i = 1; i <=n; i++){
            p[i] = sc.nextInt();
        }
        size = n;
        for(int i = n/2; i !=0;i--){
            down(i);
        }
        for(int i = 1; i <=m; i++){
            if(i == m){
                System.out.println(p[1]);
            }
            p[1] = p[size];
            size--; 
            down(1); 
        }
    }
    static void down(int u){
        int t = u;
        //如果子节点<当前节点的话就把下标位置赋给t
        if(u*2<=size&&p[u*2]<p[t]){
            t = u*2;
        }
        if(u*2+1<=size&&p[u*2+1]<p[t]){
            t = u*2+1;
        }
        if(u!=t){
            int temp = p[u];
            p[u] = p[t];
            p[t] = temp;
            down(t);
        }
    }
    
}

1.2.3使用系统自带的排序函数

import java.util.*;
class Main{
    public static void main(String []args){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int k = sc.nextInt();
        int[] arr = new int[n];
        for(int i = 0; i < n; i++){
            arr[i] = sc.nextInt();
        }
        Arrays.sort(arr);
        System.out.println(arr[k-1]);
        
    }

}

1.2.4 使用库函数的堆实现

import java.util.PriorityQueue;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int k = sc.nextInt();
        PriorityQueue<Integer> queue = new PriorityQueue<>();
        for (int i = 0; i < n; i++){
            int x = sc.nextInt();
            queue.offer(x);
        }
        for(int i = 0; i < k-1; i++){
            queue.poll();
        }
        System.out.println(queue.peek());

    }
}

2.第k大个数

地址:力扣

2.1 时间复杂度O(n)

class Solution {
    public int findKthLargest(int[] nums, int k) {
      return quick_sort(nums, 0, nums.length - 1, k - 1);
            
    }
    int quick_sort(int[] nums, int l, int r, int k) {
        if (l == r) return nums[k];
        int x = nums[l], i = l - 1, j = r + 1;
        while (i < j) {
            do i ++ ; while (nums[i] > x);
            do j -- ; while (nums[j] < x);
            if (i < j) {
                int tmp = nums[i];
                nums[i] = nums[j];
                nums[j] = tmp;
            }
        }
        if (k <= j) return quick_sort(nums, l, j, k);
        else return quick_sort(nums, j + 1, r, k);
    }

    
}

2.1.1 基于快排实现

2.2 时间复杂度O(nlogn)

2.2.1 快排后找到第k小的数

class Solution {
    public int findKthLargest(int[] nums, int k) {
     quick_sort(nums, 0, nums.length - 1);
      return nums[k-1];      
    }
    void quick_sort(int[] nums, int l, int r) {
        if (l >= r) return;
        int x = nums[l], i = l - 1, j = r + 1;
        while (i < j) {
            do i ++ ; while (nums[i] > x);
            do j -- ; while (nums[j] < x);
            if (i < j) {
                int tmp = nums[i];
                nums[i] = nums[j];
                nums[j] = tmp;
            }
        }
        quick_sort(nums, l, j);
        quick_sort(nums, j + 1, r);
    }
}

2.2.2 使用数组模拟堆来实现

class Solution {
    public int findKthLargest(int[] nums, int k) {
        int[] arr = new int[nums.length+1];
        for(int i = 1; i <= nums.length; i++){
            arr[i] = nums[i-1];
        }
        int n = nums.length;
        int size = n;
        for(int i = n/2; i !=0;i--){
            down(i,arr,size);
        }
        for(int i = 1; i <= k; i++){
            if(i == k){
                return arr[1];
            }
            arr[1] = arr[size];
            size--; 
            down(1,arr,size);
        }
        return 0;
    }
    void down(int u,int[] arr,int size){
        int t = u;
        //如果子节点<当前节点的话就把下标位置赋给t
        if(u*2<=size&&arr[u*2]>arr[t]){
            t = u*2;
        }
        if(u*2+1<=size&&arr[u*2+1] > arr[t]){
            t = u*2+1;
        }
        if(u!=t){
            int temp = arr[u];
            arr[u] = arr[t];
            arr[t] = temp;
            down(t,arr,size);
        }
    }
    
}

2.2.3 使用系统自带的排序函数

class Solution {
    public int findKthLargest(int[] nums, int k) {
      Arrays.sort(nums);
      for(int i = nums.length -1; i >= 0; i--){
          if(i == nums.length-k){
              return nums[i];
          }
      }
      return 0;
    }

    
}

2.2.4 使用库函数的堆来实现

class Solution {
    public int findKthLargest(int[] nums, int k) {
         PriorityQueue<Integer> queue = new PriorityQueue<Integer>(((o1, o2) -> {
            return o2-o1;
        }));
        for (int i = 0; i < nums.length; i++){
            
            queue.offer(nums[i]);
        }
        for(int i = 0; i < k-1; i++){
            queue.poll();
        }
        return queue.peek();
    }

    
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要输出第k小元素,可以使用数组排序或堆排序算法来实现。 方法1:数组排序 首先将给定的数组进行排序,可以使用常见的排序算法如快速排序、冒泡排序等。排序完成后,可以直接通过索引找到第k小的元素。 示例代码: ```c #include <stdio.h> void swap(int *a, int *b) { int temp = *a; *a = *b; *b = temp; } void bubbleSort(int arr[], int n) { for (int i = 0; i < n-1; i++) { for (int j = 0; j < n-i-1; j++) { if (arr[j] > arr[j+1]) { swap(&arr[j], &arr[j+1]); } } } } int main() { int arr[] = {5, 9, 3, 1, 7}; int k = 2; int n = sizeof(arr) / sizeof(arr[0]); bubbleSort(arr, n); printf("第%d小的元素是:%d\n", k, arr[k-1]); return 0; } ``` 方法2:堆排序 可以利用最小堆来实现。首先将数组构建成最小堆,然后重复k-1次从堆顶弹出元素的操作,最后堆顶元素就是第k小的元素。 示例代码: ```c #include <stdio.h> void swap(int *a, int *b) { int temp = *a; *a = *b; *b = temp; } void heapify(int arr[], int n, int i) { int smallest = i; int left = 2 * i + 1; int right = 2 * i + 2; if (left < n && arr[left] < arr[smallest]) { smallest = left; } if (right < n && arr[right] < arr[smallest]) { smallest = right; } if (smallest != i) { swap(&arr[i], &arr[smallest]); heapify(arr, n, smallest); } } int findKthSmallest(int arr[], int n, int k) { for (int i = n / 2 - 1; i >= 0; i--) { heapify(arr, n, i); } for (int i = 0; i < k - 1; i++) { swap(&arr[0], &arr[n-1]); n--; heapify(arr, n, 0); } return arr[0]; } int main() { int arr[] = {5, 9, 3, 1, 7}; int k = 2; int n = sizeof(arr) / sizeof(arr[0]); int result = findKthSmallest(arr, n, k); printf("第%d小的元素是:%d\n", k, result); return 0; } ``` 以上是两输出第k小元素的方法和示例代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值