力扣954、二倍数对数组
最近几天在字节实习,一直在看文档,跑demo,我最大的阻力竟然是电脑是个windows。。。无奈mac缺货,实习生轮不到。不过搞来搞去也是能在windows上调试了,就是有点怪,文档都是mac,windows全靠少量文档和摸索。
好久没刷题了,开始捡起来了。
链接:954. 二倍数对数组
给定一个长度为偶数的整数数组 arr
,只有对 arr
进行重组后可以满足 “对于每个 0 <= i < len(arr) / 2
,都有 arr[2 * i + 1] = 2 * arr[2 * i]
” 时,返回 true
;否则,返回 false
。
示例 1:
输入:arr = [3,1,3,6]
输出:false
示例 2:
输入:arr = [2,1,2,6]
输出:false
示例 3:
输入:arr = [4,-2,2,-4]
输出:true
解释:可以用 [-2,-4] 和 [2,4] 这两组组成 [-2,-4,2,4] 或是 [2,4,-2,-4]
提示:
0 <= arr.length <= 3 * 104
arr.length
是偶数-105 <= arr[i] <= 105
我的思路
排序,然后记录map,按照正数从大到小的顺序遍历,负数相反的顺序,同时裁剪map,如果遍历到的数找不到一半对应的值,就返回false。
class Solution {
public boolean canReorderDoubled(int[] arr) {
Map<Integer,Integer> map = new HashMap<>();
for(int i=0;i<arr.length;i++) {
map.put(arr[i],map.getOrDefault(arr[i],0)+1);
}
Arrays.sort(arr);
int i=arr.length-1;
for(;i>0;i--) {
if(arr[i]<0) break;
if(map.get(arr[i])==0) {
continue;
}
map.put(arr[i],map.get(arr[i])-1);
if(arr[i]%2==1) return false;
if(map.getOrDefault(arr[i]/2,0)==0) {
return false;
}
map.put(arr[i]/2,map.get(arr[i]/2)-1);
}
int j = i;
for(;j>=0;j--) {
if(arr[j]>=0) break;
if(map.get(arr[j])==0) {
continue;
}
map.put(arr[j],map.get(arr[j])-1);
if(map.getOrDefault(arr[j]*2,0)==0) {
return false;
}
map.put(arr[j]*2,map.get(arr[j]*2)-1);
}
return true;
}
}
优先队列
找接近零的数,找2倍,也要map记录2倍数的情况。
class Solution {
public boolean canReorderDoubled(int[] arr) {
Map<Integer,Integer> map = new HashMap<>();
// 构建最小堆,找最接近零的数(肯定没有/2的数)
PriorityQueue<Integer> pq = new PriorityQueue<>((a,b)->(Math.abs(a)-Math.abs(b)));
for(int i=0;i<arr.length;i++) {
pq.add(arr[i]);
}
while(!pq.isEmpty()) {
int cur = pq.poll();
if(map.getOrDefault(cur,0)>0) {
map.put(cur,map.get(cur)-1);
continue;
}
map.put(cur*2,map.getOrDefault(cur*2,0)+1);
}
for(int k:map.keySet()) {
if(map.get(k)!=0) {
return false;
}
}
return true;
}
}
拓扑排序
怎么说呢,这不调试半天不能全A吧。
class Solution {
public boolean canReorderDoubled(int[] arr) {
Map<Integer,Integer> cnt = new HashMap<>();
int zeroCount = 0;
for(int i=0;i<arr.length;i++) {
if (arr[i]==0) {
zeroCount++;
continue;
}
if(!cnt.containsKey(arr[i])) {
cnt.put(arr[i],1);
} else {
cnt.put(arr[i],cnt.get(arr[i])+1);
}
}
if(zeroCount%2!=0) {
return false;
}
Deque<Integer> zeroInDegree = new LinkedList<>();
Map<Integer,Integer> inDegree = new HashMap<>();
for(int k:cnt.keySet()) {
int cur = k;;
if(cur%2!=0) {
// 只能作为那个一半的数
zeroInDegree.add(cur);
} else {
// 入度等于/2的个数
int tmp = cnt.getOrDefault(cur/2,0);
inDegree.put(cur,tmp);
if(tmp==0) {
zeroInDegree.add(cur);
}
}
}
int zeroIndNum = 0;
while(!zeroInDegree.isEmpty()) {
int cur = zeroInDegree.poll();
int curOutDegree = cnt.get(cur)-inDegree.getOrDefault(cur,0);
if(curOutDegree==0) {
continue;
}
zeroIndNum+=curOutDegree;
int curNextCnt = cnt.getOrDefault(cur*2,0);
if(curNextCnt>=curOutDegree) {
zeroIndNum+=curOutDegree;
inDegree.put(cur*2,curOutDegree);
zeroInDegree.add(cur*2);
if(curNextCnt==curOutDegree&&cnt.containsKey(cur*4)) {
inDegree.put(cur*4,0);
zeroInDegree.add(cur*4);
}
}else if(curNextCnt<curOutDegree) {
return false;
}
}
System.out.println(zeroIndNum);
if(zeroIndNum+zeroCount==arr.length) {
return true;
}
return false;
}
}