2007. 从双倍数组中还原原数组https://leetcode.cn/problems/find-original-array-from-doubled-array/description/ 在做这道题时,我首先使用了sort排序,将数组中的数字从小到大排序。如果顺序遍历判断的话,可能会存在问题,如测试用例1通过不了,我最开始就犯了这个错误。
于是我就想到倒序遍历一遍数组,嵌套两层for循环,判断changed[i]是否等于2*changed[j]。代码如下:
class Solution {
public:
vector<int> findOriginalArray(vector<int>& changed) {
vector<int> tmp;
map<int,int> map;
int size = changed.size();
if(size%2) return tmp;
sort(changed.begin(),changed.end());
for(int i = size - 1; i >= 0; i--){
if(map[i] > 0)continue;
for(int j = i-1; j >= 0; j--){
if(map[j] == 0 && changed[i] == 2*changed[j] ){
tmp.push_back(changed[j]);
map[i]++;
map[j]++;
break;
}
}
if(map[i] == 0){
tmp.clear();
return tmp;
}
}
return tmp;
}
};
令我意外的是,通过大部分测试数据,但是数据量较大时超时。
于是,我又开始寻找其他方法解题,使用vector的迭代器遍历,同时一边遍历一边删除以用过的数据来减少时间。结果由于对迭代器的遍历不熟悉,发生数组越界错误。代码和错误如下:
class Solution {
public:
vector<int> findOriginalArray(vector<int>& changed) {
vector<int> tmp;
int size = changed.size();
if(size%2) return tmp;
sort(changed.begin(),changed.end());
vector<int>::iterator it1,it2;
for(it1 = changed.end(); it1 != changed.begin(); it1--){
int flag = 0;
for(it2 = it1 - 1; it2 != changed.begin(); it2--){
if(*it1 == 2*(*it2)){
tmp.push_back(*it2);
changed.erase(it2);
flag = 1;
break;
}
}
if(flag == 0){
tmp.clear();
return tmp;
}
}
return tmp;
}
};
经查询一些资料发现,end()是指向最后一个元素的下一个位置, 可以看到代码有明显错误。
修改之后测试用例还是过不了,我以为是迭代器失效的问题。
又改了,结果还是过不了。代码如下:
class Solution {
public:
vector<int> findOriginalArray(vector<int>& changed) {
vector<int> tmp;
int size = changed.size();
if(size%2) return tmp;
sort(changed.begin(),changed.end());
vector<int>::iterator it1,it2;
for(it1 = changed.end() - 1; it1 != changed.begin();){
int flag = 0;
for(it2 = it1 - 1; it2 != changed.begin(); it2--){
if(*it1 == 2*(*it2)){
cout<<*it2;
tmp.push_back(*it2);
changed.erase(it2);
it1 = changed.end() - 1;
changed.erase(it1--);
flag = 1;
break;
}
}
if(!flag){
tmp.clear();
return tmp;
}
}
return tmp;
}
};
最后,实在是想不到哪里有问题。还是看看题解吧。
/**思路与算法
首先把 changed\textit{changed}changed 排序,并且统计所有元素出现的频数。
然后我们从小到大依次遍历数组,如果对于一个元素,它的频数大于零,并且它的两倍数也还在数组中,我们则可以把它加入到答案中。
如果对于一个数找不到它两倍数,即两倍数的频数等于零,则说明无法找到原数组,返回空数组即可。
作者:力扣官方题解
链接:https://leetcode.cn/problems/find-original-array-from-doubled-array/solutions/2740671/cong-shuang-bei-shu-zu-zhong-huan-yuan-y-0vgc/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
*/
class Solution {
public:
vector<int> findOriginalArray(vector<int>& changed) {
sort(changed.begin(), changed.end());
unordered_map<int, int> count;
for (int a : changed) {
count[a]++;
}
vector<int> res;
for (int a : changed) {
if (count[a] == 0) {
continue;
}
count[a]--;
if (count[a * 2] == 0) {
return {};
}
count[a * 2]--;
res.push_back(a);
}
return res;
}
};
看了题解之后,我还是比较欣慰的,毕竟是第一次做力扣,至少第一步排序还是想到了。这一次还是学到了之前不知道的东西,如:迭代器失效和end()。还是不错的,哈哈哈哈哈哈哈~~~