赞
踩
一个整数数组
original
可以转变成一个 双倍 数组changed
,转变方式为将original
中每个元素 值乘以 2 加入数组中,然后将所有元素 随机打乱 。给你一个数组
changed
,如果change
是 双倍 数组,那么请你返回original
数组,否则请返回空数组。original
的元素可以以 任意 顺序返回。
- class Solution:
- def findOriginalArray(self, changed: List[int]) -> List[int]:
- class Solution {
- public:
- vector<int> findOriginalArray(vector<int>& changed) {
-
- }
- };
2007. 从双倍数组中还原原数组 - 力扣(LeetCode)
我们考虑将数组排序后会是什么样子?
a ... a 2a... 2a c ... c d ... d 2d ……
那么我们有一种O(nlogn)做法(也是我第一次做的时候的做法),将数组排序,然后哈希统计
然后从小到大遍历数组,用x排除2x,如果出现某个元素仍有剩余那就返回空,不然就是一个目标数组,我们在遍历的时候添加元素到返回数组即可
然后看到题解有O(n)做法
事实上不需要排序,只需哈希计数
我们发现我们只要拿到a,就能排除2a,4a……
那么我们哈希 统计后,遍历哈希表,如果x不存在x / 2在哈希表中,说明它可能是某个连续序列的起点,我们从x往下一直排除2x,4x……
如果存在cnt[x] > cnt[2x]就返回空数组
时间复杂度: O(n)空间复杂度:O(n)
- class Solution:
- def findOriginalArray(self, changed: List[int]) -> List[int]:
- mp = Counter(changed)
- cnt0 = mp.pop(0, 0) # default = 0,不存在0返回0
- if cnt0 & 1:
- return []
- ret = [0] * (cnt0 // 2)
- for x in mp:
- if x % 2 == 0 and x // 2 in mp:
- continue
- while x in mp:
- cnt = mp[x]
- if cnt > mp[x * 2]:
- return []
- ret.extend([x] * cnt)
- if cnt < mp[x * 2]:
- mp[x * 2] -= cnt
- x *= 2
- else:
- x *= 4
- return ret
-
- class Solution {
- public:
- vector<int> findOriginalArray(vector<int>& changed) {
- if(changed.size() & 1) return {};
- unordered_map<int, int> mp;
- int cnt0 = 0;
- for(auto x : changed) mp[x] ++, cnt0 += !x;
- if(cnt0 & 1) return {};
- mp.erase(0);
- vector<int> ret(cnt0 / 2);
- for(auto [k, _] : mp){
- int x = k;
- if(x & 1 || !mp.count(x / 2)){
- while(mp.count(x)){
- int cnt = mp[x];
- if(cnt > mp[x * 2]) return {};
- ret.insert(ret.end(), cnt, x);
- if(mp[x << 1] > cnt) mp[x << 1] -= cnt, x <<= 1;
- else x <<= 2;
- }
- }
- }
- return ret;
- }
- };
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。