442. 数组中重复的数据

toc

题目

给定一个整数数组 a,其中1 ≤ a[i] ≤ n (n为数组长度), 其中有些元素出现两次而其他元素出现一次。

找到所有出现两次的元素。

你可以不用到任何额外空间并在O(n)时间复杂度内解决这个问题吗?

示例:

输入:
[4,3,2,7,8,2,3,1]

输出:
[2,3]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-all-duplicates-in-an-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

瞎扯

看到这题的第一反应,这题我熟,才刚做完448,还热和着呢。
这题居然还是中等难度的, 448还是简单难度,咋感觉448还难些?难道是因为这个???


448可以用额外空间,所以官方认为更简单???

思路

同样,将nums卷起来,通过内部元素计算下标,到下标所指位置去进行染色/标记。被标记的位置的元素也存在被用来计算下标的可能,所以染色/标记方式需要可逆。对nums进行遍历,当发现下标所指位置已经被标记,说明用于计算下标的元素就是重复的元素。记录下即可。

代码

class Solution {
public:
    vector<int> findDuplicates(vector<int>& nums) {
        int iIndex = -1;
        int iOriginalSize = static_cast<int>(nums.size());
        int iData = iOriginalSize;
        nums.reserve(iOriginalSize * 2);        //先预留足够空间,后面有遍历添加操作 O(n),避免遍历添加过程频繁分配内存,影响性能
        for(int i = 0; i < iOriginalSize; i++){
            const auto& elem = nums[i];
            iIndex = std::abs(elem) - 1;        //1 ≤ a[i] ≤ n,所以需减1得到下标
            if(nums[iIndex] < 0){               //nums[iIndex]已被染色,也就是elem重复出现
                nums.push_back(iIndex + 1);     //在原始数据末尾,记录该重复元素,index + 1为元素值
                continue;
            }
            nums[iIndex] *= -1;
        }
        nums.erase(nums.begin(), nums.begin() + iOriginalSize); //去掉原始数据,保留后添加的重复数据  O(n)

        return nums;
    }
};

再瞎扯

题目要求不使用额外空间,结果大家都使用了
前面22%的提交范例使用了额外空间




后面的也都用了额外空间
我也使用了,只不过我是在原nums上增加的,这样稍微擦边球点????





posted @ 2021-05-19 20:18  無雙  阅读(80)  评论(0编辑  收藏  举报