442. Find All Duplicates in an Array。

来源:互联网 发布:运动keep是什么软件 编辑:程序博客网 时间:2024/05/20 13:18

Given an array of integers, 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others appear once.

Find all the elements that appear twice in this array.

Could you do it without extra space and in O(n) runtime?

Example:

Input:
[4,3,2,7,8,2,3,1]

Output:
[2,3]


题中说给一个整型数组,数组的范围为:1 <= a[i] <= n (这个n,就是数组的长度),然后数组中有一些元素出现两次,有一些出现一次,让我们找出出现两次的元素。

比较简单的一种做法就是用一个set,遍历数组并与set中的元素进行比较,如果set中没有该数组元素,就将数组元素放进去,如果有了就说明重复了,将其加到数组中最后返回即可。

class Solution {public:    vector<int> findDuplicates(vector<int>& nums) {        unordered_set<int> target;        vector<int> res;        for(int i=0;i<nums.size();i++) {            if(target.find(nums[i]) == target.end()) {//如果此刻该set中不存在该数字,则存放一个数字                target.insert(nums[i]);            } else {                res.push_back(nums[i]);            }        }        return res;    }};

另一种做法就是利用题中的隐含条件: 1 <= a[i] <= n (这个n,就是数组的长度),从这个条件中我们可以得到数组中的任何一个数字都要比数组的长度小或等于。

比如例子中的数组长度为8,那么数组中的元素最大值就是8。利用这一点我们可以换个思维来考虑,如果说数组中的任何元素都要小于或者等于数组的长度,那么数组中的任何元素减去1之后得到的数字正好在数组的下标之间,减去1之后,数组中的元素范围就成了:0<= a[i] <= n-1,这代表这减去1之后的数字,如果用来做原来数组的下标的话是不可能溢出的。所以我们可以遍历原来的数组,分别取出每个元素并减1,然后用得到的数字作为下标去数组中找到对应的位置,如果这个元素在数组中只出现一次,那么该元素对应的下标就只会被访问一次(除了循环遍历的那一次),相反如果这个元素在数组中出现了两次,那么该元素对应的下标就会被访问两次。

例如例子中的第一个元素:4,减去1之后对应的3作为下标,这时去访问数组中下标为3的位置,而且只会访问一次。如果是例子中的第二个数:3,减去1之后对应的2作为下标,这时去访问数组中下标为2的位置,并且在例子的七个元素也是3,减去1之后也会去访问数组中下标为2的位置。那么下标为2的位置就会被访问两次。

我么可以利用这个特点来解题,在遍历的时候取出每个元素减去1之后,拿着这个数字作为下标去数组中找到对应的位置,并且将对应位置中的数字变为负数,这样如果没有重复的话,这个负数是不会被其他下标访问到的,如果有重复的话第二次访问就会发现这个位置对应元素为负数,此刻就能说明重复了。但是有一点就是如果将数组中的元素变成负数的话,就不能正常遍历了,毕竟负数不能做为数组下标,所以此刻就可以将元素取绝对值。

举个例子:数组 [1,3,1] ,依次遍历:
第一次取出:1,减去1之后得到0,将0作为下标去访问数组中的元素,数组中下标为0的元素为1,我们将其变为负数:-1.

第二次取出:3,减去1之后得到2,将2作为下标去访问数组中的元素,数组中下标为2的元素为1,我们将其变为负数:-1.

第三次取出:1(取绝对值),减去1之后得到0,将0作为下标去访问数组中的元素,数组中下标为0的元素,发现此刻的元素为负数:-1,说明这个之前就被访问过了,说明此刻这个元素已经有了重复值。


class Solution {public:    vector<int> findDuplicates(vector<int>& nums) {        vector<int> res;        for(int n: nums) {            n = abs(n);            if(nums[n-1] > 0) {                nums[n-1] = -nums[n-1];            } else {                res.push_back(n);            }        }        return res;    }};
原创粉丝点击