215 Kth Largest Element in an Array

本文介绍了一种高效的算法来寻找未排序数组中的第K大元素。通过四种不同的方法实现,包括利用堆进行部分排序、选择排序、堆排序及快速排序的思想。其中,使用堆排序和快速排序的思想效率较高。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth distinct element.

Example 1:

Input: [3,2,1,5,6,4] and k = 2
Output: 5

Example 2:

Input: [3,2,3,1,2,4,5,5,6] and k = 4
Output: 4

Note: 
You may assume k is always valid, 1 ≤ k ≤ array's length.

这题是一道很好的面试题目,
题目短小,很快就能说清题意
有很多种解法。从简单到复杂的解法都有,梯度均匀。 不需要预先知道特殊领域知识。
这题有很多思路:
1. 按从大到小全排序,然后取第 k 个元素,时间复杂度 O(nlogn) ,空间复杂度 O(1)
2. 利用堆进行部分排序。维护一个大根堆,将数组元素全部压入堆,然后弹 出 k 次,第 k 个就是答案。时间复杂度 O(klogn) ,空间复杂度 O(n)
3. 选择排序,第 k 次选择后即可得到第 k 大的数,时间复杂度 O(nk) ,空间复杂度 O(1)
4. 堆排序,维护一个 k 大小的小根堆,将数组中的每个元素与堆顶元素进行比较,如果比堆顶元素大,则删除堆顶元素并添加该元素,如果比堆顶元素小, 则什么也不做,继续下一个元素。时间复杂度 O(nlogk) ,空间复杂
度 O(k) 。
5. 利用快速排序中的partition思想,从数组中随机选择一个元素x,把数组划分为 前后两部分 sa 和 sb , sa 中的元素小于x, sb 中的元素大于或等于x。这时有两种情况:
i. sa 的元素个数小于 k ,则递归求解 sb 中的第 k-|sa| 大的元素
ii. sa 的元素个数大于或等于 k ,则递归求解 sa 中的第 k 大的元素

时间复杂度 O(n) ,空间复杂度 O(1)

思路4和5比较高效,可以接受,其他思路太慢了,不采纳。

思路4:

class Solution {
    public int findKthLargest(int[] nums, int k) {
        Queue<Integer> q = new PriorityQueue();
        for (int i : nums) {
            if (q.size() < k) {
                q.offer(i);
            } else if (q.peek() < i) {
                q.poll();
                q.offer(i);
            }
        }
        return q.peek();
    }
}

思路5:

/**
 *
 * @author dongb
 * Kth Largest Element in an Array
 * Use partition and quick sort, then random
 * TC O(n). SC O(1)
 * 
 */
public class Solution {
    public static int findKthLargest(int[] nums, int k) {
        shuffle(nums);
        k = nums.length - k;
        int low = 0;
        int high = nums.length - 1;
        while (low < high) {
            final int pos = partition(nums, low, high);
            if (pos < k) {
                low = pos + 1;
            } else if (pos > k) {
                high = pos - 1;
            } else 
                break;
        }
        return nums[k];
    }
    
    private static int partition(int[] a, int low, int high) {
        int pivot = a[low]; // pick up the first element as pivot
        while(low < high) {
            while (low < high && a[high] >= pivot)
                high--;
            a[low] = a[high];   // from back to front find the first element smaller than pivot. Put to low.
            while (low < high && a[low] <= pivot)
                low++;
            a[high] = a[low];   // from front to back find the first element than pivot. Put to high.
        }
        a[low] = pivot; // In the end, put pivot to low
        return low;
    }
    
    private static void shuffle(int[] a) {
        final Random random = new Random();
        for (int index = 1; index < a.length; index++) {
            final int r = random.nextInt(index + 1);
            swap(a, index, r);
        }
    }
    
    private static void swap(int[] a, int i, int j) {
        final int tmp = a[i];
        a[i] = a[j];
        a[j] = tmp;
    }
    
    
    
    public static void main(String args[]) {
        Scanner cin = new Scanner(System.in);
        int k = 2;
        int[] nums = new int[6];
        for (int i = 0; i < nums.length; i++) {
            nums[i] = cin.nextInt();
        }
        int kthLargeNumber = findKthLargest(nums, k);
        System.out.println(kthLargeNumber);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值