Skip to content

Latest commit

 

History

History

2007.Find Original Array From Doubled Array

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 

English Version

题目描述

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

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

 

示例 1:

输入:changed = [1,3,4,2,6,8]
输出:[1,3,4]
解释:一个可能的 original 数组为 [1,3,4] :
- 将 1 乘以 2 ,得到 1 * 2 = 2 。
- 将 3 乘以 2 ,得到 3 * 2 = 6 。
- 将 4 乘以 2 ,得到 4 * 2 = 8 。
其他可能的原数组方案为 [4,3,1] 或者 [3,1,4] 。

示例 2:

输入:changed = [6,3,0,1]
输出:[]
解释:changed 不是一个双倍数组。

示例 3:

输入:changed = [1]
输出:[]
解释:changed 不是一个双倍数组。

 

提示:

  • 1 <= changed.length <= 105
  • 0 <= changed[i] <= 105

解法

方法一:排序

我们注意到,如果数组 changed 是一个双倍数组,那么数组 changed 中最小的元素也一定是原数组中的元素,因此,我们可以先对数组 changed 进行排序,然后以第一个元素作为起点,从小到大遍历数组 changed

我们使用一个哈希表或数组 $cnt$ 来统计数组 changed 中每个元素的出现次数。对于数组 changed 中的每个元素 $x$,我们首先检查 $x$ 是否存在于 $cnt$ 中。如果不存在,我们直接跳过这个元素。否则,我们将 $cnt[x]$ 减一,并检查 $x \times 2$ 是否存在于 $cnt$ 中。如果不存在,我们直接返回一个空数组。否则,我们将 $cnt[x \times 2]$ 减一,并将 $x$ 加入答案数组中。

遍历结束后,返回答案数组即可。

时间复杂度 $O(n \times \log n)$,空间复杂度 $O(n)$,其中 $n$ 为数组 changed 的长度。

class Solution:
    def findOriginalArray(self, changed: List[int]) -> List[int]:
        changed.sort()
        cnt = Counter(changed)
        ans = []
        for x in changed:
            if cnt[x] == 0:
                continue
            cnt[x] -= 1
            if cnt[x << 1] <= 0:
                return []
            cnt[x << 1] -= 1
            ans.append(x)
        return ans
class Solution {
    public int[] findOriginalArray(int[] changed) {
        int n = changed.length;
        Arrays.sort(changed);
        int[] cnt = new int[changed[n - 1] + 1];
        for (int x : changed) {
            ++cnt[x];
        }
        int[] ans = new int[n >> 1];
        int i = 0;
        for (int x : changed) {
            if (cnt[x] == 0) {
                continue;
            }
            --cnt[x];
            int y = x << 1;
            if (y >= cnt.length || cnt[y] <= 0) {
                return new int[0];
            }
            --cnt[y];
            ans[i++] = x;
        }
        return ans;
    }
}
class Solution {
public:
    vector<int> findOriginalArray(vector<int>& changed) {
        sort(changed.begin(), changed.end());
        vector<int> cnt(changed.back() + 1);
        for (int x : changed) {
            ++cnt[x];
        }
        vector<int> ans;
        for (int x : changed) {
            if (cnt[x] == 0) {
                continue;
            }
            --cnt[x];
            int y = x << 1;
            if (y >= cnt.size() || cnt[y] <= 0) {
                return {};
            }
            --cnt[y];
            ans.push_back(x);
        }
        return ans;
    }
};
func findOriginalArray(changed []int) (ans []int) {
	sort.Ints(changed)
	cnt := make([]int, changed[len(changed)-1]+1)
	for _, x := range changed {
		cnt[x]++
	}
	for _, x := range changed {
		if cnt[x] == 0 {
			continue
		}
		cnt[x]--
		y := x << 1
		if y >= len(cnt) || cnt[y] <= 0 {
			return []int{}
		}
		cnt[y]--
		ans = append(ans, x)
	}
	return
}
function findOriginalArray(changed: number[]): number[] {
    changed.sort((a, b) => a - b);
    const cnt: number[] = Array(changed.at(-1)! + 1).fill(0);
    for (const x of changed) {
        ++cnt[x];
    }
    const ans: number[] = [];
    for (const x of changed) {
        if (cnt[x] === 0) {
            continue;
        }
        cnt[x]--;
        const y = x << 1;
        if (y >= cnt.length || cnt[y] <= 0) {
            return [];
        }
        cnt[y]--;
        ans.push(x);
    }
    return ans;
}