二倍数对数组

108 阅读1分钟

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

说在前面

🎈今天给大家带来的是算法题,常言道:算法一时刷一时爽,时时刷时时爽🤣。保持一定的刷题频率可以在一定程度上提升自己的逻辑思考能力,还能经常学习到新的算法思路,扩展自己的解题思考库💻~

题目描述

题目简介
给定一个长度为偶数的整数数组 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 * 10^4
arr.length 是偶数
-10^5 <= arr[i] <= 10^5

思路分析

读完题目是不是觉得这道题好像很简单的样子?但是却又不知道该从何入手,那就让我们一起来分析分析该从哪里入手。
遇事不决先排序🐵,让我们以示例1[3,1,3,6]来进行分析,其排序后的结果如下👇

image.png

看了排序结果后好像还是没有什么思路怎么办?那就让我们在来找找题目中的关键信息,毫无疑问,对于每个 0 <= i < len(arr) / 2,都有 arr[2 * i + 1] = 2 * arr[2 * i]题目给出的条件就是我们需要注意的关键信息,我们从这句话中可以得出什么呢?

  • 每一个元素都能满足条件才返回 true
  • 条件为arr[2 * i + 1] = 2 * arr[2 * i] 得出这两个关键信息之后,我们再来看看数组的排序结果,其中最小的元素1的位置就很明确了,在arr[2 * i + 1] = 2 * arr[2 * i]中,它只能作为arr[2 * i]这一项,后面的元素也是同理,如果没有比它小的元素与其匹配,那么它就只能与更大的元素匹配。因此我们只要按从小到大的元素排列顺序将可以匹配成对的数对拿出,最后判断是否全部匹配上了即可。
    注意
    这里还有一点需要注意的,因为-10^5 <= arr[i] <= 10^5,arr[i]可以是负数,所以这里的排序规律并不能是单纯的从小到到排序,因为负数乘于2其值反而会变小,所以在负数部分我们应该从大到小进行排序。
keyList = keyList.sort((a, b) => {
    if (a < 0 || b < 0) return b - a;
    return a - b;
});

AC代码

JavaScript版本

/**
 * @param {number[]} arr
 * @return {boolean}
 */
var canReorderDoubled = function (arr) {
  const arrMap = {};
  //统计每一个元素的数量
  for (let i = 0; i < arr.length; i++) {
    arrMap[arr[i]] = (arrMap[arr[i]] || 0) + 1;
  }
  //进行排序
  let keyList = Object.keys(arrMap);
  keyList = keyList.sort((a, b) => {
    if (a < 0 || b < 0) return b - a;
    return a - b;
  });
  //遍历匹配
  for (let i = 0; i < keyList.length; i++) {
    const key = keyList[i];
    if (arrMap[key] == 0) {
      delete arrMap[key];
      continue;
    }
    if (!arrMap[2 * key] || arrMap[2 * key] < arrMap[key]) return false;
    arrMap[2 * key] -= arrMap[key];
    delete arrMap[key];
  }
  return Object.keys(arrMap).length == 0;
};

typeScript版本

function canReorderDoubled(arr: number[]): boolean {
  const arrMap = {};
  for (let i = 0; i < arr.length; i++) {
    arrMap[arr[i]] = (arrMap[arr[i]] || 0) + 1;
  }
  let keyList = Object.keys(arrMap);
  keyList = keyList.sort((a: string, b: string) => {
    if (parseInt(a) < 0 && parseInt(b) < 0) return parseInt(b) - parseInt(a);
    return parseInt(a) - parseInt(b);
  });
  for (let i = 0; i < keyList.length; i++) {
    const key = keyList[i];
    if (arrMap[key] == 0) {
      delete arrMap[key];
      continue;
    }
    if (!arrMap[2 * parseInt(key)] || arrMap[2 * parseInt(key)] < arrMap[key])
      return false;
    arrMap[2 * parseInt(key)] -= arrMap[key];
    delete arrMap[key];
  }
  return Object.keys(arrMap).length == 0;
}

说在后面

🎉这里是JYeontu,现在是一名前端工程师,有空会刷刷算法题,平时喜欢打羽毛球🏸 ,平时也喜欢写些东西,既为自己记录📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解🙇,写错的地方望指出,定会认真改进😊,在此谢谢大家的支持,我们下文再见🙌。