三种方法详解:剑指Offer 03. 数组中重复的数字

LeetCode:剑指Offer 03. 数组中重复的数字

文章目录

  • LeetCode:剑指Offer 03. 数组中重复的数字
    • 原题LeetCode链接:[剑指Offer 03. 数组中重复的数字](https://leetcode-cn.com/problems/shu-zu-zhong-zhong-fu-de-shu-zi-lcof/)
    • 题目:找出数组中重复的数字
    • 方法一:排序
    • 方法二:集合法、unordered_set
    • 方法三:就地交换

原题LeetCode链接:剑指Offer 03. 数组中重复的数字

题目:找出数组中重复的数字

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

示例1:

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

限制:2 ≤ n ≤ 100000

方法一:排序

​ 思路:数组元素是数字,对其进行排序,若有重复则在排序后数组的相邻位置,遍历数组即可找到。排序时间复杂度O(nlogn),空间复杂度O(1)。C++代码如下:

class Solution {
public:
    int findRepeatNumber(vector& nums) {
        sort(nums.begin(), nums.end());
        int length = nums.size();
        for(int i = 0; i < length-1; i++){
            if(nums[i] == nums[i+1]){
                return nums[i];
            }
        }
        return -1;
    }
};

tips: sort()用法:

头文件:#include
void sort (RandomAccessIterator first, RandomAccessIterator last);
void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);

first:待排序数组起始位置;

last:待排序数组末尾位置,要排序的最后一个元素的后一个元素位置,[first,last);

comp:排序的方法,可以是升序也可以是降序,不写则默认升序。

方法二:集合法、unordered_set

思路:首先构建一个空集合,然后遍历数组,如果元素不在集合中则将其插入集合中;若元素在集合中,则说明有重复。

tips :set内部使用红黑树实现,具有自动排序的功能,因此内部元素在任何时候都是有序的;unordered_set基于哈希表,数据插入和查找时间复杂度低,代价是消耗较多内存,不能自动排序。本题只需要插入与查找,因此选用unordered_set 时间上的差别可自行尝试使用两种结构进行提交。空间复杂度O(n),时间复杂度为O(n)。C++代码如下:

class Solution {
public:
    int findRepeatNumber(vector& nums) {
        unordered_set s;
        int length = nums.size();
        for(int i = 0; i < length; i++){
            if(s.find(nums[i]) == s.end()){
                s.insert(nums[i]);
            }
            else{
                return nums[i];
            }
        }
        return -1;
    }
};

方法三:就地交换

思路:因为数组中的数字都是在0~n-1范围内的,如果没有重复的元素那么数据值和下标应该是相等的。而如果有重复的值的话,有些位置放的就不是对应的值,那么我们可以尝试将它放回对应的位置。

1)如果对应的位置有一个符合的元素,就说明该数字重复了;

2)如果对应的位置也不是符合的元素,那么就将两者交换,将上一个元素和正确位置配对,继续寻找新的元素的位置。

class Solution {
public:
    int findRepeatNumber(vector& nums) {
        int length = nums.size();
        for(int i = 0; i < length; i++){
            if(i == nums[i]){//如果元素和位置对应,则继续
                continue;
            }
            else{//否则
                while(i != nums[i]){//循环,直到元素与位置对应
                    if(nums[nums[i]] == nums[i]){//此元素对应的位置上已经有一个符合的了
                        return nums[i];//说明已经重复,返回元素即可
                    }
                    else{//元素对应位置上也是不符合的元素,那么就和此元素交换使它符合,然后继续寻找新位置
                        int temp = nums[nums[i]];
                        nums[nums[i]] = nums[i];
                        nums[i] = temp;
                    }
                }
            }
        }
        return -1;
    }
};

如果有错误之处,还望指出!

你可能感兴趣的:(剑指Offer)