【LeetCode简单算法题】在长度 2N 的数组中找出重复 N 次的元素

题目描述

给你一个整数数组 nums ,该数组具有以下属性:

nums.length == 2 * n.
nums 包含 n + 1 个 不同的 元素
nums 中恰有一个元素重复 n 次
找出并返回重复了 n 次的那个元素。

 

示例 1:

输入:nums = [1,2,3,3]
输出:3
示例 2:

输入:nums = [2,1,2,5,3,2]
输出:2
示例 3:

输入:nums = [5,1,5,2,5,3,5,4]
输出:5
 

提示:

2 <= n <= 5000
nums.length == 2 * n
0 <= nums[i] <= 104
nums 由 n + 1 个 不同的 元素组成,且其中一个元素恰好重复 n 次

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/n-repeated-element-in-size-2n-array

题目本身非常简单,看了各种题解发现有很多不一样的思路,很有意思。

1. 哈希表统计

根据题目描述,我们知道重复的这个数,出现的次数是数组长度的一半,其他每个数都只会出现一次,所以实际上我们只要遍历数组,一旦发现有重复数字出现时,则就是我们要找的数字。

class Solution {
    public int repeatedNTimes(int[] nums) {
        Map<Integer, Integer> map = new HashMap<>();
        for(int num : nums){
            int val = map.getOrDefault(num, 0) + 1;  
            map.put(num, val);
            if(val > 1){
                return num;
            }
        }
        return -1;
    }
}

换成set集合,更方便

class Solution {
    public int repeatedNTimes(int[] nums) {
        Set<Integer> set = new HashSet<>();
        for (int num : nums) {
            if (!set.add(num)) {
                return num;
            }
        }
        return -1;
    }
}

复杂度分析

时间复杂度:O(n)
空间复杂度:O(n)

2. 随机选择

官方提供的一种解法,思路非常简单,每次随机选择两个不同的下标,判断它们对应的元素是否相等即可。如果相等,那么返回任意一个作为答案。

    public int repeatedNTimes(int[] nums) {
        Random random = new Random();
        int n = nums.length;
        while (true) {
            int r1 = random.nextInt(n);
            int r2 = random.nextInt(n);
            if (r1 != r2 && nums[r1] == nums[r2]) {
                return nums[r1];
            }
        }
    }

复杂度分析

双O(1)的复杂度

时间复杂度:期望O(1),选到两个相同元素的概率为:n/2n * n-1/2n ≈ 1/4(假设n为5,则数组长度为10,那么也就是50% * 40% ≈ 0.2,n越大,结果越趋近 0.25),因此期望查找4次即可完成。
空间复杂度:O(1)

3. 数学

也是官方提供的一种方式,通过数学公式推导出来,不过还是比较简单的,可以看的懂。。。

首先假设重复元素x在数组中出现的位置,如果存在每个x相邻的位置之间都至少间隔了两个其他元素,那么数组的总长度至少为:n+(n-1)*2 = 3n-2

题目中给出了n的范围:2 <= n <= 5000
以及数组的长度:nums.length == 2 * n

所以当n为2时,则需满足3n-2 > 2n,很明显不成立,所以一定存在两个相邻的x位置是连续的,或者只间隔了1位。

比如像下面这样:

x = 1,n = 2
1 2 3 1 

当n超过2,则无法满足要求了

1 2 3 1 后面还需要再加两个数,且必须有一个数是1。

那么肯定不符合每个x相邻的位置之间都至少间隔了两个其他元素

所以,这样一来,我们只需要遍历所有间隔2个以及2个以内位置的下标对(当n=2时,数组的长度最多为4,因此最多只能隔2个位置。),判断对应的元素是否相对即可。

    public int repeatedNTimes(int[] nums) {
        for (int gap = 1; gap <= 3; gap++) {
            for (int i = 0; gap + i < nums.length; i++) {
                if(nums[i] == nums[gap + i]){
                    return nums[i];
                }
            }
        }
        return -1;
    }

复杂度分析

时间复杂度:期望O(n),最多遍历3次
空间复杂度:O(1)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

码拉松

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

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

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

打赏作者

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

抵扣说明:

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

余额充值