LeetCode 2122. 还原原数组 思维+双指针

LeetCode 2122. 还原原数组

题目描述

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

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

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

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

注意:生成的测试用例保证存在 至少一个 有效数组 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]。


输入:nums = [1,1,3,3]
输出:[2,2]
解释:
如果 arr = [2,2] 且 k = 1 ,那么 lower = [1,1] 且 higher = [3,3] 。
组合 lower 和 higher 得到 [1,1,3,3] ,这是 nums 的一个排列。
注意,数组不能是 [1,3] ,因为在这种情况下,获得 [1,1,3,3] 唯一可行的方案是 k = 0 。
这种方案是无效的,k 必须是一个正整数。


输入:nums = [5,435]
输出:[220]
解释:
唯一可行的组合是 arr = [220] 且 k = 215 。在这种情况下,lower = [5] 且 higher = [435] 。

算法

(暴力枚举,双指针) \(O(n^2)\)

  1. 首先将将给定的数组从小到达排序,可以断定\(nums(0)\)\(arr [0] - k\),

  2. 枚举 \(i\),假设当前\(nums(i)\)\(arr [0] + k\),其中 \(nums(i)\)\(nums(0)\) 的差值作为 \(2k\),然后代入检验。

  3. 检验给定的差值 \(2k\) 时,可以采用双指针的方法,如果发现没有找到与当前位置匹配的数字,则返回失败。

时间复杂度

  • 最坏情况需要枚举 \(O(n)\) 次,每次枚举需要 \(O(n)\) 的时间验证,故总时间复杂度为 \(O(n^2)\)

空间复杂度

  • 需要 \(O(n)\) 的额外空间存储排序的系统栈,以及验证过程中的临时数组。

C++ 代码

class Solution {
public:
    vector<int> res;
    bool check(vector<int>& nums, int k){
        res.clear();
        vector<bool> st(nums.size(), false);
        for(int i = 0, j = 1; i < nums.size(); i++){
           
            if(st[i] == true) continue;
            while(j < nums.size() && nums[j] - nums[i] < k){
                j++;
            }
            if(j == nums.size() || nums[j] - nums[i] != k) return false;
            
            res.push_back(nums[i] + k / 2);
            st[j] = true;
            j++;
        }
        return true;
    }
    vector<int> recoverArray(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        int k = 0;
        for(int i = 1; i < nums.size(); i++){
            k = nums[i] - nums[0];
            if(k == 0 || (k & 1)) continue;
            if(check(nums, k)){
                break;
            }
        }
        return res;
    }
};
posted @ 2022-01-02 22:59  pxlsdz  阅读(59)  评论(0编辑  收藏  举报