剑指offer50_数组中重复的数字_题解

数组中重复的数字

题目描述

在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中第一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。

返回描述:

如果数组中有重复的数字,函数返回true,否则返回false。

如果数组中有重复的数字,把重复的数字放到参数duplication[0]中。(ps:duplication已经初始化,可以直接赋值使用。)

分析

方案一:哈希算法(hash)

算法流程:

  1. 初始化: 新建 \(map\) ,记为 \(dic\)
  2. 遍历数组 \(nums\) 中的每个数字 \(num\)
    1. \(num\)\(dic\) 中,说明重复,返回 \(num\)
    2. \(num\) 添加至 \(dic\) 中;
  3. 返回 \(false\)

代码

/**
1.时间复杂度:O(n) 
2.空间复杂度:O(n)
**/
class Solution
{
public:
    bool duplicate(int numbers[], int length, int* duplication) 
    {
        map<int, bool> dic;

        for (int i = 0; i < length; i++)
        {
            int num = numbers[i];
            dic[num] = dic.find(num) == dic.end();
            if (!dic[num])
            {
                *duplication = num;
                return true;
            }
        }
        return false;
    }
};

方案二:原地算法(in-place)

算法思想:

利用现有数组设置标志,当一个数字被访问过后,设置该数字对应索引的数值 \(-n\)

当再次遇到相同数字时,会发现该数字对应索引上的数值已经小于0,直接返回这个数即可。

算法流程:

  1. 遍历数组 \(numbers\) 的每个数字 \(num\)
    1. 设置索引 \(index\)\(num\)
    2. \(index<0\) 时,将 \(index\)\(n\) 作为索引,保证 \(index\) 始终为初始值
      1. \(numbers[index]>=0\) 时,将 \(numbers[index]\)\(n\),由于每个数字 \(num\) 保证在 \([0,n-1]\),所以一定有 \(numbers[index]<0\) ,代表 \(index\) 已经被访问过
      2. \(numbers[index]<0\) 时,说明 \(index\) 指向的该数字之前已经被访问过,返回 \(index\) 即可
  2. 返回 \(false\) ,没有找到该数字

代码

/**
1.时间复杂度:O(n) 
2.空间复杂度:O(1)
**/
class Solution
{
public:
    bool duplicate(int numbers[], int length, int *duplication)
    {
        for (int i = 0; i < length; i++)
        {
            int index = numbers[i];
            if (index < 0)
            {
                index += length;
            }
            if (numbers[index] >= 0)
            {
                numbers[index] -= length;
            }
            else
            {
                duplication[0] = index;
                return true;
            }
        }
        return false;
    }
};
posted @ 2021-02-17 17:08  RiverCold  阅读(29)  评论(0编辑  收藏  举报