开启我的LeetCode刷题日记:954. 二倍数对数组

95 阅读1分钟

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

编程世界总是离不了算法

最近在看框架源码时,会有很多算法的实现逻辑,有时候会感到吃力

于是决定蹭着假期,加强算法和数据结构相关的知识

那怎么提升呢?

其实我知道算法这东西没有捷径,多写多练才能提升,于是我开启我的LeetCode刷题之旅

第一阶段目标是:200道,每天12

为了不乱,本系列文章目录分为三部分:

  1. 今日题目:xxx
  2. 我的思路
  3. 代码实现

今天题目: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

来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/ar… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

我的思路

  • 使用 Map 记录所有的数字,以及出现的次数,在后续匹配中,用于冲销已匹配的个数
  • 使用 sort 排序,使数组排列成[-2, -4, 2, 4],正数增序,负数降序的形式,使偶数位(例如0)和奇数位(例如1)能够匹配
  • 处理相同数据连续出现的情况,例如[1, 1, 2, 2],此时偶数位(例如0)和奇数位(例如1)不能匹配,当整体是匹配的,使用 Set 去重
  • for 循环匹配,因为数据去重了,且正、负按要求排列了,所以此时判断偶数位(例如0)和奇数位(例如1)能够匹配上即可,
  • 因为第 0 位的数字在数组中不存在 /2 的数,所有的匹配关系都是向后匹配,即仅仅需要判断 *2 的情况
  • 因为所有的数字都可能出现多次,但因为是向后匹配,所以 *2 的数字出现次数应大于当前数字出现次数,否则匹配失败

代码实现

var canReorderDoubled = function(arr) {
  let map = new Map()
  for(let i = 0; i<arr.length; i++) { // 用于记录数字出现次数
    map.set(arr[i], (map.get(arr[i]) || 0)+1)
  }
	arr.sort((a, b)=>{ // 将数组排序成符合2倍数的形式[-2, -4, 2, 4]
    if(a>0 || b>0) {
      return a-b
    } else {
      return b-a
    }
  })

  let vals = [...new Set(arr)] // 去重 [1, 1, 2, 2]
  for(let i=0; i<vals.length;i++) {
    // 因为数据去重了,且正、负按要求排列了,因此所有的匹配关系都是向后匹配
    // 因为所有的数字都可能出现多次,所以 *2 的数字出现次数应大于当前数字出现次数,否则匹配失败
    let temp = (map.get(vals[i]*2) || 0) - map.get(vals[i])
    if(temp<0) {
      return false
    }
    map.set(vals[i]*2,  temp)
  }
  return true
};


总结

实现方式其实有很多,这里仅供参考~

由于刚开始刷题,也不知道从哪里刷好,如果前辈们有好的建议,希望不吝赐教,感谢🌹