剑指 offer 数组算法题:数组中重复的数字

题目描述:在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。

分析:

哈希计数,统计元素出现次数,在统计的过程中,如果哈希表中已经存在该元素则说明重复。

indexOf + lastIndexOf,遍历数组,找到首次出现和最后一次出现不同的元素。

数组原地交换,数字范围在 0~n-1,且数组长度为 n, 说明不重复的数字均可以在等于下标的位置上,遍历数组将不等于下标的元素a与以该元素值a作为下标的元素值b进行对比,若相等,说明该元素值a重复,否则交换两个元素值再寻找以b为下标的元素值c进行对比,直到原a位置的元素等于下标。

集合,遍历数组将集合中没有的元素放入集合中,若集合中已经存在该元素,说明重复。

求解:

// 哈希计数
function findRepeatNumber1(nums: number[]): number {
  const len = nums?.length;
  // 进行计数
  const countMap: Record<number, number> = {};
  for (let i = 0; i < len; i++) {
    const element = nums[i];
    const count = countMap[element];
    if (count) {
      return element;
    } else {
      countMap[element] = 1;
    }
  }
  return NaN;
}

// indexOf + lastIndexOf
function findRepeatNumber2(nums: number[]): number {
  const len = nums?.length;
  for (let i = 0; i < len; i++) {
    const element = nums[i];
    if (nums.indexOf(element) !== nums.lastIndexOf(element)) {
      return element;
    }
  }
  return NaN;
}

// 数组原地交换
function findRepeatNumber3(nums: number[]): number {
  const len = nums?.length;
  for (let i = 0; i < len; i++) {
    // 如果 0 ~ n -1 的数字都只出现一次,那么排序后就会满足 element === i
    // element !== i 说明可能是重复的数字,
    while (nums[i] !== i) {
      const element = nums[i];
      const target = nums[element]; // 而当前数字应该存在的位置所对应的元素值
      if (element === target) {
        // 相等说明一定重复
        return element;
      } else {
        // 不等,交换, 直到应该存在的位置所对应的元素值也放到正确位置
        [nums[i], nums[element]] = [nums[element], nums[i]];
      }
    }
  }
  return NaN;
}

// 集合
function findRepeatNumber4(nums: number[]): number {
  const len = nums?.length;
  const set = new Set();
  for (let i = 0; i < len; i++) {
    const element = nums[i];
    if (set.has(element)) {
      // 集合中存在该元素
      return element;
    } else {
      // 不存在,则加进去
      set.add(element);
    }
  }
  return NaN;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

薛定谔的猫96

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值