2021 阿里巴巴 2星题 完美对

链接:完美对_阿里巴巴笔试题_牛客网
来源:牛客网
 

有 n\ n n个物品,每个物品有 k\ k k个属性,第 i\ i i件物品的第 j\ j j个属性用一个正整数表示记为ai,ja_{i,j}ai,j​,两个不同的物品 i,j\ i,j i,j被称为是完美对的当且仅当ai,1+aj,1=ai,2+aj,2=⋯=ai,k+aj,ka_{i,1}+a_{j,1} = a_{i,2}+a_{j,2}=\dots=a_{i,k}+a_{j,k}ai,1​+aj,1​=ai,2​+aj,2​=⋯=ai,k​+aj,k​,求完美对的个数。

进阶:时间复杂度O(nlogn) O(nlogn)\ O(nlogn) ,空间复杂度O(n) O(n)\ O(n) 

输入描述:

第一行两个数字 n,k\ n,k n,k。

接下来 n\ n n行,第 i\ i i行 k\ k k个数字表示ai,1,ai,2,…,ai,ka_{i,1}, a_{i,2},\dots,a_{i,k}ai,1​,ai,2​,…,ai,k​。

1≤n≤105,2≤k≤10,1≤ai≤1001 \leq n \leq 10^5, 2 \leq k \leq 10, 1 \leq a_i \leq 1001≤n≤105,2≤k≤10,1≤ai​≤100


 

输出描述:

一行一个数字表示答案

示例1

输入

5 3
2 11 21
19 10 1
20 11 1
6 15 24
18 27 36

输出

3

思路

先找到差分和相同的行

再在差分和相同的行内找完美对

链接:完美对_阿里巴巴笔试题_牛客网
来源:牛客网
 

对于物品i,其属性差分和diffSum为aik-aik-1+...+ai2-ai1+ai1-ai0=aik-ai0

对于物品j,其属性差分和diffSum为ajk-ajk-1+...+aj2-aj1+aj1-aj0=ajk-aj0

对于完美对(i, j),各属性之和相等,因此将以上两式相加可以得到aik+ajk-(ai0+aj0)=0,即完美对的属性差分和互为相反数。

也就是说先满足差分和互为相反数,再满足完美对 

代码

import java.util.*;
import java.io.*;
public class Main{
    public static void main(String[] args) throws IOException{
        BufferedReader read = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));
        String[] in = read.readLine().trim().split(" ");
        int n = Integer.parseInt(in[0]),k = Integer.parseInt(in[1]);
        int[][] f = new int[n][k];
        Map<Integer,List<Integer>> map = new HashMap();
        int count = 0;
        for(int i=0;i<n;i++){
            in = read.readLine().trim().split(" ");
            for(int j=0;j<k;j++){
                f[i][j] = Integer.parseInt(in[j]);
            }
            int diff = f[i][k-1]-f[i][0];
            if(map.containsKey(-diff)){
                List<Integer> temp = map.get(-diff);
                for(int j:temp){
                    if(isValid(i,j,f)){
                        count++;
                    }
                }
            }
            if(map.containsKey(diff)){
                map.get(diff).add(i);
            }else{
                List<Integer> temp = new ArrayList();
                temp.add(i);
                map.put(diff,temp);
            }
        }
        writer.write(Integer.toString(count));
        writer.newLine();
        writer.flush();
    }
    private static boolean isValid(int i,int j,int[][] f){
        int[] f1 = f[i],f2 = f[j];
        int val = f1[0]+f2[0];
        for(int t=1;t<f1.length;t++){
            if(f1[t]+f2[t]!=val)return false;
        }
        return true;
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值