记录 力扣 2007 题

2007. 从双倍数组中还原原数组icon-default.png?t=N7T8https://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()。还是不错的,哈哈哈哈哈哈哈~~~

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值