力扣2122-还原原数组-枚举+离散化

6 篇文章 0 订阅
2 篇文章 0 订阅

题目描述:

Alice 有一个下标从 0 开始的数组 arr ,由 n 个正整数组成。她会选择一个任意的 正整数 k 并按下述方式创建两个下标从 0 开始的新整数数组 lower 和 higher :

  • 对每个满足 0 <= i < n 的下标 i ,lower[i] = arr[i] - k
  • 对每个满足 0 <= i < n 的下标 i ,higher[i] = arr[i] + k

不幸地是,Alice 丢失了全部三个数组。但是,她记住了在数组 lower 和 higher 中出现的整数,但不知道每个整数属于哪个数组。请你帮助 Alice 还原原数组。

给你一个由 2n 个整数组成的整数数组 nums ,其中 恰好 n 个整数出现在 lower ,剩下的出现在 higher ,还原并返回 原数组 arr 。如果出现答案不唯一的情况,返回 任一 有效数组。

输入输出:

输入:nums = [2,10,6,4,8,12]
输出:[3,7,11]
解释:
如果 arr = [3,7,11] 且 k = 1 ,那么 lower = [2,6,10] 且 higher = [4,8,12] 。
组合 lower 和 higher 得到 [2,6,10,4,8,12] ,这是 nums 的一个排列。
另一个有效的数组是 arr = [5,7,9] 且 k = 3 。在这种情况下,lower = [2,4,6] 且 higher = [8,10,12] 。

提示:

2 * n == nums.length
1 <= n <= 1000
1 <= nums[i] <= 109
生成的测试用例保证存在 至少一个 有效数组 arr

大概思路:

n是1e3,时间复杂度n2
第一层循环,枚举k的取值,第二层循环,考察k的取值是否正确。
数字范围1e9,需要离散化。元素在数组内的位置无意义(数值x可能出现多次),先排序,方便离散化等操作。
实现细节见代码注释。

代码如下:

const int N=1010;
class Solution {
    int lower[N<<1];
    vector<int>vec[N<<1];//vec[i]表示数值i所在位置有哪些 
    int cnt[N<<1];//数值i已被配对了哪些 
    int b[N<<1];//用于离散 
    int en;//用于离散 
public:
    int getid(int x)
    {
        return lower_bound(b,b+en,x)-b;
    }
    vector<int> recoverArray(vector<int>& nums) {
        int ct=0;//离散数组内元素个数
        sort(nums.begin(),nums.end());
        int len=nums.size();
        //离散化
        for(int i=0;i<len;i++)
            b[ct++]=nums[i];
        sort(b,b+ct);
        en=unique(b,b+ct)-b;
        //准备遍历 
        for(int i=0;i<len;i++)
            vec[getid(nums[i])].push_back(i);
        int k,ca;
        //第一层,枚举k的取值 
        for(int i=1;i<len;i++)
        {
        	//k不能为0,且lower[i]与higher[i]必须为偶数 
            if(nums[i]==nums[0]||(nums[i]-nums[0])%2==1)continue;
            //尝试获取k值,每次都要初始化cnt数组以及lower数组的指针ca 
            ca=0;
            for(int j=0;j<len;j++)
                cnt[j]=0;
            k=(nums[i]-nums[0])>>1;
            cnt[getid(nums[0])]++;
            cnt[getid(nums[i])]++;
            lower[ca++]=nums[0];
            for(int j=0;j<len;j++)
            {
                int x=getid(nums[j]);
                int y=getid(nums[j]+2*k);
                if(b[y]!=nums[j]+2*k)continue;//判定一下数值b[y]是否存在 
                if(cnt[x]==vec[x].size())continue;//所有数值b[x]已经被配对 
                if(cnt[y]<vec[y].size())
                {
                    lower[ca++]=nums[j];
                    cnt[x]++;
                    cnt[y]++;
                }
                else break;
            }
            if(ca==len/2) break;//lower数组已经被找到 
        }
        vector<int>u;//准备返回答案 
        for(int i=0;i<ca;i++)
            u.push_back(lower[i]+k);
        return u;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值