持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第5天,点击查看活动详情
每日刷题 2022.10.02
- leetcode原题链接:leetcode.cn/problems/ar…
题目
- 给定一个长度为偶数的整数数组 arr,只有对 arr 进行重组后可以满足 “对于每个 0 <= i < len(arr) / 2,都有 arr[2 * i + 1] = 2 * arr[2 * i]” 时,返回 true;否则,返回 false。
示例
输入: arr = [3,1,3,6]
输出: false
解题思路
拓展
- 自定义排序
sort()
: 因为我们需要找到符合要求的数对,且arr[i] -> 2 * arr[i]
,因此需要按照数的大小进行排序,非递减。
分析
- 根据题意可知:
- 所给的
arr
长度为偶数 - 可对数组重组,对于每个
0 <= i < len(arr) / 2
,需要满足arr[2 * i + 1] = 2 * arr[2 * i]
.- 假设:当前的数组长度为4(偶数),那么对于每一个
0 <= i < 2
,也就是数组长度为4时,数组中的arr[1] = 2 * arr[0]、arr[3] = 2 * arr[2]
- 由此可见:只需要保证每个数对中:一个数是另外一个数的2倍即可。
- 假设:当前的数组长度为4(偶数),那么对于每一个
- 总结:给你一个数组
arr
,判断数组是否能拆分成每个都符合要求的数对。因为不需要输出重组后的数组,因此不论如何排序均可。
- 所给的
实现
- 不论是从小到大还是从大到小都可以,这里我选择从小到大,因为这样就只需要计算乘法,可以避开
/2
的情况 - 预处理:将数组排序,需要(自定义)按照数字的绝对值来进行排序,数值小的放在数值大的前面,因为需要将第一个数作为基准,去查找其
2
倍的数,是否存在。 - 使用
map
集合:记录数组中每个数值出现的次数。 for
循环遍历的每一个数值,都是作为基准出现的。- 预判断,如果当前的基准出现的次数已经全部被匹配完成,为
0
,那么就直接跳过,查找下一个基准 - 从下标
0
开始,通过map
查找其在数组中出现过的次数,去查找和其匹配的2倍的数值是否存在; - 如果存在,还需要判断2倍的数值的出现次数是否大于等于当前基准的出现次数.
- 如果大于等于,则说明基准出现的次数全部找到匹配的,则将其置
0
- 如果小于,则表示基准出现的次数不能够全部被匹配上,那么此时就应该返回
false
- 如果大于等于,则说明基准出现的次数全部找到匹配的,则将其置
- 如果不存在,则表示找不到匹配的,此时就应该返回
false
- 预判断,如果当前的基准出现的次数已经全部被匹配完成,为
- !!注意!!:数组中如果存在
0
的话,会出现错误- 因为在
map
集合中0
和0
会被当做一个数值来进行计算,自己减去自己并不能算匹配成功 - 因此,需要通过
map
集合中存储的0
数值的个数来进行判断- 奇数:没有办法完全匹配,返回
false
- 偶数:可以自己完成匹配,查找下一个基准
- 奇数:没有办法完全匹配,返回
- 因为在
代码
/**
* @param {number[]} arr
* @return {boolean}
*/
var canReorderDoubled = function(arr) {
// 排序
let len = arr.length, map = new Map();
arr.sort((a, b) => {
return Math.abs(a) - Math.abs(b);
});
// console.log(arr)
for(let i = 0; i < len; i++) {
map.set(arr[i], (map.get(arr[i]) || 0) + 1)
}
// console.log(map)
let set = new Set(arr)
// console.log(set)
for(let i = 0; i < len - 1; i++) {
if(arr[i] == 0){
if (map.get(0) % 2 == 0) continue;
else return false;
}
if(map.get(arr[i]) == 0) continue;
if(map.has(arr[i] * 2)){
if(map.get(arr[i] * 2) >= map.get(arr[i])){
map.set(arr[i] * 2, map.get(arr[i] * 2) - map.get(arr[i]))
map.set(arr[i], 0);
}else {
return false;
}
}else {
return false;
}
}
return true;
};