954.二倍数对数组

难度:中等

目录

一、问题描述

二、解题思路

1、思路

2、极端情况判断

3、极端情况解决

三、解题

1、代码实现​​​​​​​

2、时间复杂度 and 空间复杂度


一、问题描述

这里直接采用LeetCode上面的问题描述。

给定一个长度为偶数的整数数组 arr,只有对 arr 进行重组后可以满足 “对于每个 0 <= i < len(arr) / 2,都有 arr[2 * i + 1] = 2 * arr[2 * i]” 时,返回 true;否则,返回 false

下面给出示例:

提示:

  • 0 <= arr.length <= 3 * 104
  • arr.length 是偶数
  • -105 <= arr[i] <= 105

二、解题思路

1、思路

        看题目,该题就是一个数进行配对的题目,每个数都要配对一个两倍于自己的数,直至全部配对之后即可返回 true, 否则直接返回 false

        这里我们可以采用排序加 哈希表进行计数。排序的操作是为了让数组有序,这样大的负数可以配对两倍自己的小负数,大的整数可以配对二分之一自己的小整数。这是重点。

        遍历一遍 arr ,将小的负数存储进哈希表并计数,大的负数用来匹配 2 倍自身的小负数,匹配成功的话将小负数的计数器 --;匹配失败将自己存入到哈希表中并且计数器 ++。对于正数来说还需要进行一个判断,因为是 int 型的数,那么奇数是不可能的做到 大于 0 且为正数的奇数:item = 2*(item/2)这是不相等的,因此只要判断大偶数是否存在自己一半的数是否存在哈希表之中,存在的话将其计数器 --,不存在则将该数存入哈希表并且计数器 ++

        最后遍历哈希表,看哈希表中的被统计的数的计数器是否有不为 0 的情况,有的话直接返回false,因为没有完全配对,没有最后则返回 true

2、极端情况判断

        这里的 0 是一个特殊情况。

3、极端情况解决

        当存在 0 的时候 0 将被累计并且统计到计数器之中,最后遍历哈希表的时候判断 0 的个数是否是偶数即可,是偶数则说明可以一一配对成功,否则不可以。

三、解题

1、代码实现

class Solution {
public:
    bool canReorderDoubled(vector<int>& arr) {
        unordered_map<int,int> hash;
        //这里排序过后使得大的负数接近0,小的正数接近于0
        sort(arr.begin(),arr.end());
        for(auto& i: arr) {
            //如果 i 是偶数 并且大于0 并且哈希表中有其一半的数存在,将 i/2 计数进行减一
            //因为是排过序的 所以只能是后面大的正整数查看是否有自己 1/2 的正整数(这点很重要)
            //这里进行是否是偶数的判断是因为 奇数是不可能 满足 整型的 i = 2倍的 i/2的
            if(!(i%2) and i > 0 and hash[i/2]){
                hash[i/2]--;
            }
            //如果小于 0 那么 小的负数是不会有比自己还小的两倍关系的负数 
            //因此这里进行 * 2,将大的负数缩小两倍查看之前是否存储过 小两倍的负数 有的话计数器--
            else if (i < 0 and hash[i*2]){
                hash[i*2]--;
            }
            else {
                hash[i]++;
            }
        }
        for(auto& item : hash){
            //判断 0 的个数是否是偶数,是的话继续,否则return false
            if(!item.first){
                if(!(item.second % 2)){
                    continue;
                }
                return false;            
            }
            //判断该数的 计数器是否清零 若没有清零则说明没有一一配对 return false
            if(item.second){
                return false;
            }
        }
        //全部配对 return true
        return true;
    }
};

2、时间复杂度 and 空间复杂度

时间复杂度:O(n)

空间复杂度:O(n)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_Alkaid_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值