题目
public static final int TARGET = 100;
int isPair(int a, int b) {
int sum = a+b;
return sum > TARGET ? 1 : sum < TARGET ? -1 : 0;
}
int countPair(int array[]) {
//todo
}
这个题目很有意思,在
isPair()
的方法中,故意用了三目运算的方式绕了一个圈的要表达sum==100
。在java
中,compare()
方法的返回规则是:
- 两数
相等
返回0a>b
的时候返回1a<b
的时候返回-1这里是用了
compare()
方法的思想来放回比较大小的结果。
- 在数组中找出相加和为TARGET的2个数,统计他们的组合数量,需要去重,效率小于o(n^2)
解题方法
如果是一个乱序的序列,那么则需要先排序,排序可以用很多中方法,我这里直接调用了Arrays.sort();
package com.jimmy.lib;
import java.util.Arrays;
public class FindSum {
public static void main(String[] args) {
int arr[] = {1, 99, 101, 1, 99};
// 1. 先排序
Arrays.sort(arr);
// 2. 开始计算
int i = countPair(arr);
System.out.println(i);
}
private static final int TARGET = 100;
private static int isPair(int a, int b) {
int sum = a + b;
return sum > TARGET ? 1 : sum < TARGET ? -1 : 0;
}
private static int countPair(int array[]) {
int left = 0;
int right = array.length - 1;
int count = 0;
while (left < right) {
int pair = isPair(array[left], array[right]);
if (pair == 0) {
count++;
left = addLeft(array, left);
right = subRight(array, right);
} else if (pair == 1) {
right = subRight(array, right);
} else {
left = addLeft(array, left);
}
}
return count;
}
private static int subRight(int[] array, int right) {
int lastRight = array[right--];
while (right >= 0 && array[right] == lastRight) {
right--;
}
return Math.max(right, 0);
}
private static int addLeft(int[] array, int left) {
int lastLeft = array[left++];
while (left < array.length && array[left] == lastLeft) {
left++;
}
return Math.min(left, array.length - 1);
}
}
思路
- 先排序这个序列
- 用2个指针,左右两边开始循环,计算left+right的值是否等于target
- 如果相等则 增加left,减少right,记录次数
- 如果大于target,则减少right
- 如果小于target,则增加left
- 而去重的关键:就在于如何增加left和如何减少right。
- 在增加left的时候,先记录当前的left,如果下一个left和当前的left相同,那就继续增加left
- 在减少right的时候,先记录当前的right,如果新的right和当前的right相同,那就继续减少
按照这种思路即可输出序列对。这个应该是快排的思想。
总结
- 解决数组的题目一般有这几种思想方法:
- 先判断数组是否有序,无序则要思考是否先排序后更好解决问题。
- 思考
有序序列
二分查找法是否能否找到解。 - 思考
快速排序
的思想,前后两个指针是否能够找到解。 - 思考用从
头部或尾部开始的
快慢指针的思想是否可以找到解。 - 思考
堆排序
的思想是否可以找到解。 - 判断是否和
树
相关,如果相关则记住左子树(left)和右子树(right)的算法- 左子树:2*n+1
- 右子树:2*n+2
- 判断是否需要使用位运算中的
异或
运算