215 Kth Largest Element in an Array

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、付费专栏及课程。

余额充值