Back
Featured image of post Largest Val in my mind xD

Largest Val in my mind xD

Find who's the K

Leetcode K-Largest Val

215. 数组中的第K个最大元素 , 题目需要 在未排序的数组找到第 k 个最大的元素 ,而且不是第k个不同的元素

先看简单方法,用Java的PriorityQueue来解答,需注意的是PriorityQueue是用小顶堆实现的

public int findKthLargest2(int[] nums, int k) {
        PriorityQueue<Integer> pq = new PriorityQueue<>();
		//小顶堆去除元素
        for (int num : nums) {
            pq.offer(num);
            if (pq.size() > k) {
                //因为我们只需要找到第K大的数,超过size直接去除堆顶元素就好
                pq.poll();
            }
        }
        return pq.peek();
    }

亦或者和官方解答一样,用大顶堆实现也可以得出第K大的数

public int findKthLargest(int[] nums, int k) {
            int heapSize = nums.length;
            buildMaxHeap(nums, heapSize);
            for (int i = nums.length - 1; i >= nums.length - k + 1; --i) {
                swap(nums, 0, i);
                --heapSize;
                maxHeapify(nums, 0, heapSize);
            }
            return nums[0];
        }

        public void buildMaxHeap(int[] a, int heapSize) {
            for (int i = heapSize / 2; i >= 0; i--) {
                maxHeapify(a, i, heapSize);
            }
        }

        public void maxHeapify(int[] a, int i, int heapSize) {
            int l = i * 2 + 1, r = i * 2 + 2, largest = i;

            if (l < heapSize && a[l] > a[largest]) {
                largest = l;
            }
            if (r < heapSize && a[r] > a[largest]) {
                largest = r;
            }
            if (largest != i) {
                swap(a, i, largest);
                maxHeapify(a, largest, heapSize);
            }
        }

        private void swap(int[] nums, int i, int j) {
            int temp = nums[i];
            nums[i] = nums[j];
            nums[j] = temp;
        }

第三种方法则是用quickSelectionSort 快速选择排序

public int findKthLargest(int[] nums, int k) {
        int low = 0, high = nums.length - 1;
    	//因为无法保证每次pivot都是正中间的索引的
    	//所以我们需要对数组进行一次随机洗牌
        shuffle(nums);
        k = nums.length - k;

        while (low <= high) {
            int p = partition(nums, low, high);
            if (p < k) {
                low = p + 1;
            } else if (p > k) {
                high = p - 1;
            } else {
                return nums[p];
            }
        }
        return -1;
    }

    private int partition(int[] nums, int lo, int hi) {
        if (lo == hi) {
            return lo;
        }
        int pivot = nums[lo];
        // j = hi + 1 因为 while 中会先执行--
        int i = lo, j = hi + 1;

        while (true) {
            // 保证 nums[lo..i] 都小于 pivot
            while (nums[++i] < pivot) {
                if (i == hi) {
                    break;
                }
            }
            // 保证 nums[j..hi] 都大于 pivot
            while (nums[--j] > pivot) {
                if (j == lo) {
                    break;
                }
            }
            if (i >= j) {
                break;
            }
		   //到了这一步的时候
            //一定会有nums[i] > pivot && nums[j] < pivot
            //因此我们要交换num[i]和num[j]
            //保证nums[low..i] < pivot < nums[j..high]
            swap(nums, i, j);
        }

        //交换pivot
        swap(nums, j, lo);
	   // 现在 nums[low..j-1] < nums[j] < nums[j+1..high]
        return j;
    }

    private void shuffle(int[] nums) {//随机打乱
        int n = nums.length;
        Random ran = new Random();
        for (int i = 0; i < n; i++) {
            int r = i + ran.nextInt(n - i);
            swap(nums, i, r);
        }
    }

    private void swap(int[] nums, int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
Welcome to the world of Minezeratul