二倍数对数组

145 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情

一、题目

leetcode 二倍数对数组

给定一个长度为偶数的整数数组 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

二、题解

1.解读 仔细分析题目发现其实就是找数组中为两倍关系的一对对元素,可以对数组重组就是可以任意选择数组元素,但是不能重复选择;因为数组元素个数肯定是偶数个,所以数组中的len/2对元素如果都满足两倍关系就是满足条件可以返回true的,否则就返回false的。

方法一 对于arr数组的元素arr[i]来说,我们要找到其他的一个等于2 * arr[i]的元素,存在这个元素那么就是找到了一对数,还要找数组其余的对数了;否则找不到是不符合要求的。因为原数组是无序的,如果我们要找2 * arr[i],就得确定arr[i],所以可以先将arr排序,这样arr[i]都是在前半部分了;因为数组内的元素是可以重复的,那么我们可以先记录下arr数组中所有元素的个数,然后寻找符合条件的若干对数字,找到一对就将对应的元素个数减掉。具体的首先使用map哈希表记录arr数组的元素个数,然后将map哈希表的key元素按照绝对值排序成arrList数组,然后就遍历排序的arrList元素,对于arrList的当前元素num,要到map哈希表中查询2 * num元素的数量,如果找不到该对应的元素或者num元素的数量比2 * num元素的数量还要多,那就是不成对的,可以直接结束返回false;否则就将2 * num的元素个数减掉num的元素个数,说明num元素成功匹配了对数。因为数组元素都是偶数个,最后遍历完元素都能有匹配的就可返回true。

三、代码

方法一 Java代码

class Solution {
    public boolean canReorderDoubled(int[] arr) {
        HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
        for (int num : arr) {
            map.put(num, map.getOrDefault(num, 0) + 1);
        }
        List<Integer> arrList = new ArrayList<Integer>();
        for (Integer num : map.keySet()) {
            arrList.add(num);
        }
        arrList.sort((a, b) -> Math.abs(a) - Math.abs(b));

        for (Integer num : arrList) {
            Integer n = map.get(num);
            Integer n2 = map.getOrDefault(2 * num, 0);
            if (n > n2) {
                return false;
            }
            map.put(2 * num, n2 - n);
        }
        return true;
    }
}

时间复杂度:O(n),需要对数组元素排序、以及遍历一次数组元素。


空间复杂度:O(n),需要一个哈希表记录数组元素个数。