力扣周赛 2491. 划分技能点相等的团队

题目:

给你一个正整数数组 skill ,数组长度为 偶数 n ,其中 skill[i] 表示第 i 个玩家的技能点。将所有玩家分成 n / 2 个 2 人团队,使每一个团队的技能点之和 相等 。

团队的 化学反应 等于团队中玩家的技能点 乘积 。

返回所有团队的 化学反应 之和,如果无法使每个团队的技能点之和相等,则返回 -1 。

示例 1:

输入:skill = [3,2,5,1,3,4]
输出:22
解释:
将玩家分成 3 个团队 (1, 5), (2, 4), (3, 3) ,每个团队的技能点之和都是 6 。
所有团队的化学反应之和是 1 * 5 + 2 * 4 + 3 * 3 = 5 + 8 + 9 = 22 。
示例 2:

输入:skill = [3,4]
输出:12
解释:
两个玩家形成一个团队,技能点之和是 7 。
团队的化学反应是 3 * 4 = 12 。
示例 3:

输入:skill = [1,1,2,3]
输出:-1
解释:
无法将玩家分成每个团队技能点都相等的若干个 2 人团队。
 

提示:

2 <= skill.length <= 105
skill.length 是偶数
1 <= skill[i] <= 1000

题解:

方法一:

通过研究我们可以想到当数组(前提是有序)首尾元素配对时获得每队数据相加都相同的几率最大。第一个数和最后一个数配对,第二个和倒数第二个等等。现将数据排序,再求和sum,用sum/配对的个数即length/2就是配对后的两数相加的值。判断首尾元素相加是否等于sum/(length/2)

 
    public long dividePlayers(int[] skill) {
       int len=skill.length;
     long sum=0;
       if(len==2){
           return skill[0]*skill[1];
       }
        Arrays.sort(skill);
       for(int i=0;i<len;i++){
           sum+=skill[i];
       }
       if(sum%(len/2)!=0){
           return -1;
       }
      int r=0;
       int l=len-1;
       long sum1=0;
       int num=(int)(sum/(len/2));
       while (r<l){
           if(skill[r]+skill[l]==num){
               sum1+=skill[r]*skill[l];
               r++;
               l--;
           }
           else {
               return -1;
           }
       }
       return  sum1;
    }

方法二:

运用hash表。

用哈希表hash记录每个数字出现的次数,求出所有元素的和sum,用sum/(length/2)得出符合题意的团队的和num(num必为整数否则1返回-1)。如果hash[num-x]==0及与x配对的值不存在则取出x当hash[num-x]存在是时,把x*(num-x)加到答案ans中,然后判断参与计算的数字是否刚好为数组长度 ,最后返回答案的一半。

class Solution {
    public long dividePlayers(int[] skill) {
        var map = new HashMap<Long,Integer>();
        long sum = 0;
        int l = skill.length;
       

        for(int item:skill){
            sum+=item;
        }
        if(sum%(l/2)!=0){
            return -1;
        }
        long num = sum/(l/2);
        long ans = 0;
        long count = 0;
        for(long item:skill){
            int temp = map.getOrDefault(num-item,0);
            if(temp != 0){
                count+=2;
                ans+=(num-item)*item;
                map.put(num-item,temp-1);
            }else{
               
                 map.put( item,map.getOrDefault(item,0)+1);
            }
        }
        //判断参与计算的数字是否刚好为数组长度,否则返回-1
        return count == l? ans:-1;
    }
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值