Study Notes
  • Kuma Blog
  • AI
    • AI-Resources
    • AI-books
    • Prompts
      • Prompts Free Courses
  • Movies
    • 2024
    • 2024
    • 2024
  • Google
    • chunked-palindrome
  • Setup
    • How to add a new user into Ubuntu and setup ssh key?
    • How to set up VSCode remote server connect with browser with Docker
  • kubernetes
  • Books
    • Designing-Data-Intensive-Applications
      • 第一章 — 可靠性,可扩展性,可维护性的应用程序(Reliable, Scalable, and Maintainable Applications)
    • System-Performance
      • Design-Data-Intensive-Application
      • Chapter 2: Methodologies
  • Languages
    • japanese
      • japanese-week
  • Leetcode
    • 30DayChallenge
      • LRU-cache
      • backspace-string-compare
      • binary-tree-maximum-path-sum
      • bitwise-and-number-range
      • check-string-valid-sequence-from-root-to-leaves-path-in-bst
      • construct-binary-search-tree-from-preorder-traversal
      • contiguous-array
      • counting-elements
      • diameter-of-binary-tree
      • first-unique-number
      • group-anagrams
      • jump-game
      • last-stone-weight
      • leftmost-column-with-at-least-a-one
      • longest-common-subsequect
      • maximal-square
      • maximum-subarray
      • middle-of-the-linked-list
      • min-stack
      • minimun-path-sum
      • move-zeroes
      • perform-string-shifts
      • product-of-array-except-itself
      • search-in-rotated-sorted-array
      • subarray-sum-equals-k
      • valid-parenthesis-string
    • English Solution
      • 1168.optimize-water-distribution-in-a-village-en
      • 1171.remove-zero-sum-consecutive-nodes-from-linked-list-en
      • 1177.can-make-palindrome-from-substring-en
      • 1343.number-of-avg-subarr-sizek-greater-or-equal-threshold
      • 1345.jump-game-iv
      • 25.reverse-nodes-in-k-groups-en
      • 474.ones-and-zeros-en
      • 53.maximum-sum-subarray-en
      • 547.friend-circles-en
      • 79.word-search-en
    • May2020Challenge
      • check-if-straight-line
      • cousins-in-binary-tree
      • find-town-judge
      • first-bad-version
      • first-unique-character-in-a-string
      • flood-fill
      • implement-trie
      • jewels-and-stones
      • majority-element
      • maximum-sum-circular-subarray
      • number-complement
      • odd-even-linkedlist
      • ransom-note
      • remove-k-digits
      • single-element-in-sorted-array
      • valid-perfect-square
    • python
      • 000017-Letter-Combinations-of-a-Phone-Number
      • 000032-Longest-Valid-Parentheses
      • 000033-Search-in-Rotated-Sorted-Array
      • 000046-Permutations
      • 000074-Search-a-2D-Matrix
      • 000077-Combinations
      • 000081-Search-in-Rotated-Sorted-Array-II
      • 000137-single-number-ii
      • 000139-Word-Break
      • 000207-courses-schedule
      • 000209-Minimum-Size-Subarray-Sum
      • 000376-wiggle-subsequence
      • 000445-Add-Two-Numbers-II
      • 000486-Predict-the-Winner
      • 000518-Coin-Change-II
      • 000673-Number-of-Longest-Increasing-Subsequence
      • 000688-Knight-Probability-in-Chessboard
      • 000735-Asteroid-Collision
      • 000852-Peak-Index-in-a-Mountain-Array
      • 859-Buddy-Strings
      • 000864-Shortest-Path-to-Get-All-Keys
      • 000920-Number-of-Music-Playlists
      • 001218-Longest-Arithmetic-Subsequence-of-Given-Difference
      • 001235-Maximum-Profit-in-Job-Scheduling
      • 001493-Longest-Subarray-of 1-After-Deleting-One-Element
      • Problem
      • 002024-Maximize-the-Confusion-of-an-Exam
      • 2305-Fair-Distribution-of-Cookies
      • 002616-Minimize-the-Maximum-Difference-of-Pairs
      • 00802-Find-Eventual-Safe-States
    • 中文版解题
      • 1147.longest-chunked-palindrome-decomposition-cn
      • 1168.optimize-water-distribution-in-a-village-cn
      • 1171.remove-zero-sum-consecutive-nodes-from-linked-list-cn
      • 1177.can-make-palindrome-from-substring-cn
      • 215.kth-largest-element-in-an-array-cn
      • 25.reverse-nodes-in-k-groups-cn
      • 30.substring-with-concatenation-of-all-words-cn
      • 4.median-of-two-sorted-array-cn
      • 460.LFU-cache-cn
      • 474.ones-and-zeros-cn
      • 53.maximum-sum-subarray-cn
      • 79.word-search-cn
  • Readings
    • 2020
      • Design-Data-Intensive-Application
      • 亲爱的提奥
      • 理想国
      • 贫穷的本质
Powered by GitBook
On this page
  • 题目地址
  • 题目描述
  • 思路
  • 解法一 (排序)
  • 复杂度分析
  • 解法二 - 小顶堆(Heap)
  • 复杂度分析
  • 解法三 - Quick Select
  • 复杂度分析
  • 关键点分析
  • 代码(Java code)
  • 参考(References)

Was this helpful?

  1. Leetcode
  2. 中文版解题

215.kth-largest-element-in-an-array-cn

Previous1177.can-make-palindrome-from-substring-cnNext25.reverse-nodes-in-k-groups-cn

Last updated 5 years ago

Was this helpful?

题目地址

题目描述

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.

思路

这道题要求在一个无序的数组中,返回第K大的数。根据时间复杂度不同,这题有3种不同的解法。

解法一 (排序)

很直观的解法就是给数组排序,这样求解第K大的数,就等于是从小到大排好序的数组的第(n-K)小的数 (n 是数组的长度)。

例如:

[3,2,1,5,6,4], k = 2
1. 数组排序:
 [1,2,3,4,5,6],
2. 找第(n-k)小的数
 n-k=4, nums[4]=5 (第2大的数)

复杂度分析

时间复杂度: O(nlogn) - n 是数组长度。 空间复杂度: O(1) - 原数组排序,没有用到额外空间

解法二 - 小顶堆(Heap)

可以维护一个大小为K的小顶堆,堆顶是最小元素,当堆的size > K 的时候,删除堆顶元素. 扫描一遍数组,最后堆顶就是第K大的元素。 直接返回。

复杂度分析

时间复杂度:O(n * logk) , n is array length

空间复杂度:O(k)

跟排序相比,以空间换时间。

解法三 - Quick Select

Quick Select 类似快排,选取pivot,把小于pivot的元素都移到pivot之前,这样pivot所在位置就是第pivot index 小的元素。 但是不需要完全给数组排序,只要找到当前pivot的位置是否是在第(n-k)小的位置,如果是,找到第k大的数直接返回。

具体步骤:

1. 在数组区间随机取`pivot index = left + random[right-left]`. 
2. 根据pivot 做 partition,在数组区间,把小于pivot的数都移到pivot左边。
3. 得到pivot的位置 index,`compare(index, (n-k))`.
    a. index == n-k -> 找到第`k`大元素,直接返回结果。
    b. index < n-k -> 说明在`index`右边,继续找数组区间`[index+1, right]`
    c. index > n-k -> 那么第`k`大数在`index`左边,继续查找数组区间`[left, index-1]`.

例子,【3,2,3,1,2,4,5,5,6], k = 4

如下图:

复杂度分析

时间复杂度:

  • 平均是:O(n)

  • 最坏的情况是:O(n * n)

关键点分析

  1. 直接排序很简单

  2. 堆(Heap)主要是要维护一个K大小的小顶堆,扫描一遍数组,最后堆顶元素即是所求。

  3. Quick Select, 关键是是取pivot,对数组区间做partition,比较pivot的位置,类似二分,取pivot左边或右边继续递归查找。

代码(Java code)

解法一 - 排序

class KthLargestElementSort {
 public int findKthlargest2(int[] nums, int k) {
    Arrays.sort(nums);
    return nums[nums.length - k];
  }
}

解法二 - Heap (PriorityQueue)

class KthLargestElementHeap {
  public int findKthLargest(int[] nums, int k) {
      PriorityQueue<Integer> pq = new PriorityQueue<>();
      for (int num : nums) {
        pq.offer(num);
        if (pq.size() > k) {
          pq.poll();
        }
      }
      return pq.poll();
  }
}

解法三 - Quick Select

class KthLargestElementQuickSelect {
    static Random random = new Random();
    public int findKthLargest3(int[] nums, int k) {
      int len = nums.length;
      return select(nums, 0, len - 1, len - k);
    }

    private int select(int[] nums, int left, int right, int k) {
      if (left == right) return nums[left];
      // random select pivotIndex between left and right
      int pivotIndex = left + random.nextInt(right - left);
      // do partition, move smaller than pivot number into pivot left
      int pos = partition(nums, left, right, pivotIndex);
      if (pos == k) {
        return nums[pos];
      } else if (pos > k) {
        return select(nums, left, pos - 1, k);
      } else {
        return select(nums, pos + 1, right, k);
      }
    }

    private int partition(int[] nums, int left, int right, int pivotIndex) {
      int pivot = nums[pivotIndex];
      // move pivot to end
      swap(nums, right, pivotIndex);
      int pos = left;
      // move smaller num to pivot left
      for (int i = left; i <= right; i++) {
        if (nums[i] < pivot) {
          swap(nums, pos++, i);
        }
      }
      // move pivot to original place
      swap(nums, right, pos);
      return pos;
    }

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

参考(References)

例如:

https://leetcode.com/problems/kth-largest-element-in-an-array/
Quick Select Wiki
quick select
heap