返回

发现数据世界的隐秘宝藏——算法揭示数组中反复出现的数字及最小的数字

前端

算法的世界里,总有一些神奇的操作能够帮助我们解决各种各样的问题。今天,我们就来看看一个非常有趣的算法问题——找出数组中出现次数超过一半的数字以及最小的k个数。

寻找数组中出现次数超过一半的数字

首先,我们来看一下如何找到数组中出现次数超过一半的数字。这个问题乍一看似乎很难,但实际上有一个非常简单的算法可以解决它。这个算法叫做“摩尔投票法”。

摩尔投票法的基本思想是,如果一个数字出现次数超过数组长度的一半,那么它在数组中出现的次数肯定会比其他任何数字都多。因此,我们可以先给这个数字记上1票,然后遍历整个数组,如果遇到相同的数字就给它记上1票,如果遇到不同的数字就把之前记的票减1票。如果在遍历完整个数组之后,这个数字的票数仍然大于0,那么它就是出现次数超过一半的数字。

function findMajorityElement(arr) {
  let count = 0;
  let majorityElement = null;
  for (let i = 0; i < arr.length; i++) {
    if (count === 0) {
      majorityElement = arr[i];
      count = 1;
    } else {
      if (majorityElement === arr[i]) {
        count++;
      } else {
        count--;
      }
    }
  }
  if (count > 0) {
    return majorityElement;
  }
  return null;
}

寻找数组中最小的k个数

接下来,我们再来看看如何找到数组中最小的k个数。这个问题同样有一个非常简单的算法可以解决它,这个算法叫做“快速选择算法”。

快速选择算法的基本思想是,我们可以通过一次划分将数组分成两部分,一部分包含所有大于等于第k个最小数字的数字,另一部分包含所有小于第k个最小数字的数字。然后,我们只需要在其中一部分中继续寻找第k个最小数字即可。

function findKthSmallestElement(arr, k) {
  if (arr.length < k) {
    return null;
  }
  return quickSelect(arr, 0, arr.length - 1, k);
}

function quickSelect(arr, left, right, k) {
  if (left === right) {
    return arr[left];
  }
  let pivotIndex = partition(arr, left, right);
  if (pivotIndex === k - 1) {
    return arr[pivotIndex];
  } else if (pivotIndex < k - 1) {
    return quickSelect(arr, pivotIndex + 1, right, k);
  } else {
    return quickSelect(arr, left, pivotIndex - 1, k);
  }
}

function partition(arr, left, right) {
  let pivot = arr[right];
  let i = left - 1;
  for (let j = left; j < right; j++) {
    if (arr[j] < pivot) {
      i++;
      swap(arr, i, j);
    }
  }
  swap(arr, i + 1, right);
  return i + 1;
}

function swap(arr, i, j) {
  let temp = arr[i];
  arr[i] = arr[j];
  arr[j] = temp;
}

希望这些算法能够帮助你解决你遇到的问题。如果你还有其他问题,欢迎随时咨询我。