【力扣刷题】961. 重复 N 次的元素【Set 优化 + 连续子序列分析】

331 阅读2分钟

「这是我参与11月更文挑战的第 15 天,活动详情查看:2021最后一次更文挑战

原题链接

961. 重复 N 次的元素 - 力扣(LeetCode) (leetcode-cn.com)

题目描述

在大小为 2N 的数组 A 中有 N+1 个不同的元素,其中有一个元素重复了 N 次。

返回重复了 N 次的那个元素。

测试用例

示例 1:

输入:[1,2,3,3]
输出:3

示例 2:

输入:[2,1,2,5,3,2]
输出:2

参数限制

  • 4 <= A.length <= 10000
  • 0 <= A[i] < 10000
  • A.length 为偶数

分析

题目简洁明了,在长度为 2n 的数组中,有一个元素重复了 n,那么我们统计这个数组中各个元素重复出现的次数,只要有一个元素重复的次数达到了 n 次,那么这个数就是我们需要求的数

代码

var repeatedNTimes = function(nums) {
    let half = nums.length / 2;
    let obj = {};
    for (let i = 0; i < nums.length; i++) {
        let m = obj[nums[i]] || 0;
        if (m == half - 1) return nums[i];
        obj[nums[i]] = m + 1;
    }
    return -1;
};

image.png

性能有点拉垮??再读题,数组长度为 2n,其中有 n+1 个元素,有一个元素重复了 n 次,那么,剩下的 n 个元素,占据了数组中的剩余的 n 个位置

换个说法,只要有一个元素重复了 2 次,那么这个数就一定是我们需要查找的数

为了提高检索的效率,我们需要引入一个 Set,每个数字先去 set 里查找,没有则添加到 set, 如果找到了,就说明上一次已经添加了,即已经出现过,这个时候我们直接返回这个数即可

优化

var repeatedNTimes = function(nums) {
    let set = new Set();
    for (let i = 0; i < nums.length; i++) {
        let n = nums[i];
        if(set.has(n))return n;
        set.add(n);
    }
    return -1;
};

image.png

相比上一种方法,只需要找到重复 2 此的数字即可立即返回,执行的效率就好上很多

扩展

换一个思路,现有 n 个各不相同的数字组成的数组,我们再吧 n 个相同但不同于之前的数字,插入前一步的数组里,理想情况,相同数字直接相邻;次一级的情况,相同数字间隔一个;最次的情况,相同的数字间有 2 个不同的数据,这三种的示例如下:

1, 1, 2, 3
1, 2, 1, 3
1, 2, 3, 1

鉴于这种思路,我们只需要按序获取 4 个相邻的数字,从头往后遍历,就一定能获取到重复的数字,这种方法就可以去掉 set 辅助


今天的力扣刷题就分享到这里,感谢大家的阅读~