【双指针】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

答案

链接

  题目可理解为将一个数组分割成两个数组,其中一个数组的所有元素*2等于另一个数组,可先对原数组进行自定义排序,随后用双指针的方式挑选出大小关系为2倍的数字。自定义排序用于保证对于[2, 4, 1, 8]这种情况2与4不会先于1与2进行配对,同时绝对值保证对于[-2,-4]这种情况排序后-2排在-4前,负数小于正数/负数大于正数用于保证一次配对后end指针不会从头重新遍历。


class Solution {
public:
    
    bool canReorderDoubled(vector<int>& arr) { //双指针
        sort(arr.begin(),arr.end(), [](int v1, int v2){ //自定义排序,先按正负数排大小,再按照数的绝对值排大小
            if(v1 == v2) //相等必须返回false,不然会溢出 https://blog.csdn.net/albertsh/article/details/119523587
                return false;
            else if(v1<=0 && v2>=0)
                return true;
            else if(v1>=0 && v2<=0)
                return false;
            else {
                return fabs(v1) <= fabs(v2);
            }
        });
        
        // for(int i=0;i<arr.size();i++) 
        //    cout << arr[i] << " ";
        
        vector<bool> ismarked = vector<bool>(arr.size(), false); //判断是否已用于之前的组合
        int front = 0, end = 1;
        while(front < end && end < arr.size()) { 
            if(ismarked[front]==true) { //如果当前值被使用过则跳过
                front++;
                if(front >= end) { //front < end
                    end++;
                }
            }
            else if(ismarked[end]==true) { //如果当前值被使用过则跳过
                end++;
            }
            else if(2 * arr[front] == arr[end]) { //如果两个值都未使用过,且成二倍关系则两者配对,指针均后移。
                ismarked[front] = true;
                ismarked[end] = true;
                front++;
                end++;
            }
            else {             //如果两个值不成2倍关系,则end向后面查找,排序后前面一定不存在未配对的元素与arr[front]成2倍关系的情况
                end++;
            }
        }

        for(int i=0;i<ismarked.size();i++) { //如果全部被标记,即被配对则true,否则false
            if(ismarked[i]==false)
                return false;
        }
        return true;

    }
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

wjh776a68

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

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

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

打赏作者

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

抵扣说明:

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

余额充值