【Leetcode】2007. 从双倍数组中还原原数组

文章讲述了如何通过给定一个已打乱并可能包含重复元素的双倍数组changed,使用C++的unordered_map数据结构高效地找到原始数组original。关键步骤包括排序、计数元素出现次数以及匹配二倍值。
摘要由CSDN通过智能技术生成

题目描述

题目链接
一个整数数组original可以转变成一个双倍数组changed,转变方式为将original中每个元素值乘以2加入数组中,然后将所有元素随机打乱

给你一个数组changed,如果change双倍数组,那么请你返回original数组,否则请返回空数组。original的元素可以以任意顺序返回。

题目分析

这题难点在于随机打乱,并且我们要根据一个元素去找另一个元素(二倍值)。我们可以对整个changed进行排序,这样第一个元素肯定就不是二倍值,我们想判断它的二倍值是否存在,最简单粗暴的方法就是往后遍历,但是这样做效率肯定就很低,那么我们能想到一个查询为O(1)的方法——把他们用map保存起来,其中key是该元素值,value是这个元素出现的次数。

为什么要统计出现次数?我们判断某一个元素changed[i]的二倍值是否存在,即其二倍值出现的次数map[2*changed[i]]是否不为0。若存在,则将该元素放入original中,并且将它的二倍值减1,因为我们不希望往后遍历的时候再去碰到这个二倍值,同时,因为这个元素已经被我们放进original了,该元素出现的次数也要减1

cpp代码

于是我们可以写出下面的代码:

class Solution {
public:
    vector<int> findOriginalArray(vector<int>& changed) {
        // 如果changed的元素个数不是2的倍数,则一定不是双倍数组
        if(!changed.size() % 2) return {};

        sort(changed.begin(), changed.end());  // 首先将changed排序
        unordered_map<int, int> map; // 利用map来记录每一个元素出现的次数
        for(int i : changed) {
            map[i]++;   // 元素作为key,出现次数为value
        }

        vector<int> original;
        for(int j : changed) {
            if(map[j] != 0) {
                if((j && map[j * 2] != 0) || (!j && map[j] > 1)) {    // 如果2*j在map中出现过,则说明有配对
                    map[j * 2]--;
                    original.push_back(j);
                    map[j]--;   //j出现次数也要-1,因为我们拿出了一个放进了original
                }
                else return{};
            }
            else continue;
        }
        return original;
    }
}; 

需要注意的是,我对元素值为0的进行了单独的判断,也就是if语句中的:j && map[j] > 1。因为0的二倍值就是它自己,所以他的二倍值出现次数和本身出现次数都存放在map的key0value中。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值