计算数组里面有多少对数之和等于指定的数,数组元素可以相等(同一个元素重复出现),配对过的index不能再次配对

本文介绍了一种时间复杂度为O(n)的高效算法,用于寻找数组中和为特定数值的数对。算法通过使用哈希表记录元素与目标和之间的差值及其频率,快速匹配对数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

现在把算法逻辑实现如下:
用例:
输入{1,1,99},100;返回1
输入{1,1,99,99},100;返回2
输入{5,8,1,9,10,99,2,3,98,98},100,返回2

 static int countSum(int[] items, int sum) {
        //key: item元素与sum之差,value: 差出现的次数(相当于元素出现的次数)
        HashMap<Integer, Integer> hashMap = new HashMap<>();
        int count = 0;
        for (int i = 0; i < items.length; i++) {
            int tmp = sum - items[i];
            if (hashMap.containsKey(tmp)) {
                hashMap.replace(tmp, hashMap.get(tmp) + 1);
            } else {
                //这里所有不同元素与sum之差都会被put进来
                hashMap.put(tmp, 1);
            }
            //只有一个数时继续
            if (i == 0) {
                continue;
            }
            Integer integer = hashMap.get(items[i]);
            if ((integer) != null) {
                    //删除一对相加等于sum的两个数
                    removeOrMinus(hashMap,items[i],integer);
                    removeOrMinus(hashMap,sum - items[i],integer);
                    count++;
            }
        }
        return count;
    }


    static void removeOrMinus(HashMap<Integer, Integer> hashMap, Integer key, Integer value) {
        if (value != null) {
            if (!value.equals(1)) {
                hashMap.replace(key, value - 1);
            } else {
                hashMap.remove(key);
            }
        }
    }

该算法核心思想是先将sum与数组里面的元素差值put到hashmap里,key为差值,value为这个元素在数组中出现的次数,然后用数组中的元素值作为查询key去查询hashmap里是否存在键值对,如果存在就说明出现过与当前元素值之和等于sum的数,因为hashmap里存的是差,当前元素等于差就说明当前元素与算出这个差的数之和为sum,这样就找到了一对这样的组合,找到之后移除一个这样的组合(两个数)并count ++,移除的时候计算这对组合每个出现的次数,大于1的则减1,等于1的则删除;hashmap查询复杂度一般O(1),一个for循环时间复杂度为O(n),这样就实现了一个时间复杂度为O(n)的算法。

Dominik设想了一个正整数数组p1,…,pn。我们把排序后的数组表示为q1,…,qn。 此外,他设想了一套允许的替换。如果一对(X,Y)是允许替换集合的成员,Dominik可以交换数组p中XY位置的字。 Marin给DominikQ查询,每个都是以下类型之一: 交换位置AB的字。 将对(A,B)添加到允许替换的集合中。Marin可以给出一对(A,B)它已经在允许替换的集合中了。 看看是否有可能只使用允许的替换对数组进行排序?替换可以以任意顺序使用,并且每个替换可以进行任意次。 如果仅使用允许的替换就可以将位置a的字转移到位置B,那么我们将这对位置(a,B)连接起来。我们称与位置A相关的所有位置的集合为A的云。如果从云中的每个位置j都有可能使用一系列允许的替换来实现p j ​ =q j ​ ,那么云就是好的。 你必须回答有多少对不同的位置(A,B)存在,使其成立: a.位置a位置B没有链接 b. A云不好,B云也不好 c.如果我们在允许替换的集合中加入一对(A,B), A的云(通过连接A的云B的云)就会变得很好。 请注意:配对(A,B)(B,A)被认为是相同的一对。 输入格式: 第一行输入包含整数NQ(1≤N,Q≤1000000)。 输入的第二行包含N个整数p1,…,pn(1≤p1,…,pn≤1000000)。 下面的每个Q行包含一个格式如下的查询:  第一行的字是集合{1,2,3,4}中的查询类型T。  如果查询T的类型是1或2,后面有两个不同的整数AB(1≤A,B≤N),代表了替换(A,B)。 输出格式: 对于类型为3或4的每个查询,在其单独的行中输出答案。 查询类型3的答案是“DA”(克罗地亚语表示“是”)或“NE”(克罗地亚语表示“否”),没有引号,而查询类型4的答案是任务中的一个非负整数。 得分: 在占总分50%的测试用例中,它将保持N, Q≤1000。 用C++编写
最新发布
06-27
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值