现在把算法逻辑实现如下:
用例:
输入{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)的算法。