Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

【排序算法】如何从数组中快速查找第K大元素? #32

Open
slogeor opened this issue Sep 4, 2019 · 1 comment
Open
Labels
数据结构 数据结构

Comments

@slogeor
Copy link
Owner

slogeor commented Sep 4, 2019

简单粗暴法

对数据元素进行排序,然后直接访问第K个元素,时间复杂度是排序算法,最快是 O(nlogn)

借助快排思想

快速排序算法的思想是分治分区,基本操作如下:

  • 步骤1:从数组[0...n] 选择分区点 ,将数组分成 3 个部分,[0...p-1], [p], [p+1, n]
    • k = p + 1,[p] 就是第 k 大元素
    • k > p+1,k 出现在后半部分
    • k < p+1,k 出现在前半部分
  • 继续步骤1

时间复杂度:n + n/2 + n/4 + n/8 +.... + 1 = 2n-1,故时间复杂度是 O(n)

@slogeor slogeor added the 数据结构 数据结构 label Sep 4, 2019
@slogeor
Copy link
Owner Author

slogeor commented Sep 5, 2019

code

/**
 * @description 查找数组中第 K 大的元素
 * @param {Array} arr
 * @param {Number} k
 * @returns {Number} k
 */
function findKthNum(arr = [], k) {
  // 异常处理
  if (arr.length === 0 || k < 1 || arr.length < k) return -1;
  // 边界处理
  if (arr.length === 1 && k === 1) return arr[0];

  var len = arr.length;
  var i = 0;
  // 分区点
  var pivot = len - 1;
  for (var j = 0; j < len; j++) {
    if (arr[j] < arr[pivot]) {
      // 数据交换
      if (i !== j) {
        var temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
      }
      i++
    }
  }

  // 分区点,要记得返回 arr[pivot],不能返回 arr[k]
  if (k === i + 1) {
    return arr[pivot];
  }

  // 后半部分
  if (k > i + 1) {
    return findKthNum(arr.slice(i, len - 1), k - i - 1);
  }

  // 前半部分
  if (k < i + 1) {
    return findKthNum(arr.slice(0, i), k);
  }
}

findKthNum([1, 3, 2, 5, 4, 6, 9, 8, 7], 8); // 8
findKthNum([1, 2, 3, 4, 5, 6, 7, 8, 9], 4); // 4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
数据结构 数据结构
Projects
None yet
Development

No branches or pull requests

1 participant