*leetcode 215. 数组中的第K个最大元素

【题目】215. 数组中的第K个最大元素

在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。

示例 1:

输入: [3,2,1,5,6,4] 和 k = 2
输出: 5

示例 2:

输入: [3,2,3,1,2,4,5,5,6] 和 k = 4
输出: 4

【解题思路1】

先排序,然后直接返回 nums.length-k 位置的元素就是第k大元素

class Solution {
    public int findKthLargest(int[] nums, int k) {
        //插入排序
        for(int i=1; i<nums.length; i++){
            int temp = nums[i]; //暂存要插入的元素
            int j = i;
            while( j>0 && temp<nums[j-1]){
                nums[j] = nums[j-1]; //如果要插入的元素小于当前元素,当前元素后移
                j--;
            }
            nums[j] = temp; //找到要插入的位置,插入元素
        }
        return nums[nums.length-k];
    }
}

【解题思路2】小顶堆

建立小顶堆,并保持堆的大小<=k,这样最后堆顶就是第k大元素
动图演示可以参考官方题解

class Solution {
    public int findKthLargest(int[] nums, int k) {
        buildHeap(nums, k); //先用前k个元素原地建堆
        for(int i=k; i<nums.length; i++){
            if(nums[i] < nums[0]){
                continue;
            }
            swap(nums, i, 0);
            heapify(nums, k, 0);
        }
        return nums[0];
    }

    //建堆
    public void buildHeap(int[] a, int k){
        for(int i=k/2-1; i>=0; i--){
            heapify(a, k, i);
        }
    }

    public void heapify(int[] a, int k, int i){
        int min = i;
        while(true){
            if(i*2+1<k && a[i*2+1]<a[i]){
                min = i*2+1;
            }
            if(i*2+2<k && a[i*2+2]<a[min]){
                min = i*2+2;
            }
            if(min==i){
                break;
            }
            swap(a, i, min);
            i = min;
        }
    }

    public void swap(int[] a, int n, int m){
        int temp = a[n];
        a[n] = a[m];
        a[m] = temp;
    }
}

【解题思路3】快排 (待研究)

第k大元素也是第 N-K 小元素,利用快排的性质不断缩小范围

  • 随机选择一个枢轴,使用划分算法将枢轴放在数组中的合适位置 pos。
  • 将小于枢轴的元素移到左边,大于等于枢轴的元素移到右边。
  • 比较 pos 和 N - k 以决定在哪边继续递归处理。

在这里插入图片描述

class Solution {
    public int findKthLargest(int[] nums, int k) {
        int size = nums.length;
        // kth largest is (N - k)th smallest
        return quickselect(nums, 0, size - 1, size - k);
    }

    public void swap(int[] nums, int a, int b) {
        int tmp = nums[a];
        nums[a] = nums[b];
        nums[b] = tmp;
    }


    public int partition(int[] nums, int left, int right, int pivot_index) {
        int pivot = nums[pivot_index];
        // 1. move pivot to end
        swap(nums, pivot_index, right);
        int store_index = left;

        // 2. move all smaller elements to the left
        for (int i = left; i <= right; i++) {
            if (nums[i] < pivot) {
            swap(nums, store_index, i);
            store_index++;
            }
        }

        // 3. move pivot to its final place
        swap(nums, store_index, right);

        return store_index;
    }

    public int quickselect(int[] nums, int left, int right, int k_smallest) {
        /*
        Returns the k-th smallest element of list within left..right.
        */

        if (left == right) // If the list contains only one element,
            return nums[left];  // return that element

        // select a random pivot_index
        Random random_num = new Random();
        int pivot_index = left + random_num.nextInt(right - left); 

        pivot_index = partition(nums, left, right, pivot_index);

        // the pivot is on (N - k)th smallest position
        if (k_smallest == pivot_index)
            return nums[k_smallest];
        // go left side
        else if (k_smallest < pivot_index)
            return quickselect(nums, left, pivot_index - 1, k_smallest);
        // go right side
        return quickselect(nums, pivot_index + 1, right, k_smallest);
    }

}
发布了134 篇原创文章 · 获赞 132 · 访问量 16万+

猜你喜欢

转载自blog.csdn.net/XunCiy/article/details/105225426
今日推荐