题目
给定一个整数数组 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上增加的,这样稍微擦边球点????