import com.google.common.base.Preconditions;
import java.util.Arrays;
/**
* 在递增排序的数组中,找到和为指定值的两个元素。若存在多对这样的元素,则找到任意一对即可。
*
* 输入一个正数sum,打印出所有和为sum的连续正数序列(序列中最少2个数字)。
*/
public class GetNumbersWithSumInArray {
/**
* 在递增排序的数组中,找到和为指定值的两个元素。若存在多对这样的元素,则找到任意一对即可。
*
* 思路:
* 1)定义两个指针:第一个指针small指向数组的第一个元素(即最小元素),第二个指针big指向数组的最后一个元素(即最大元素)。
* 2)若两个指针指向的元素的和currentSum大于指定的和sum,则big指针向前移动(目的是为了减小currentSum的值),
* 3)若两个指针指向的元素的和currentSum小于指定的和sum,则small指针向后移动(目的是为了增加currentSum的值),
* 4)若两个指针指向的元素的和currentSum等于指定的和sum,则返回。
*
* 时间复杂度O(n)
*
* @param array 递增排序的数组
* @param sum 指定的和
* @return
*/
public static int[] getNumbersWithSum(int[] array, int sum) {
Preconditions.checkArgument(null != array && array.length >= 2);
int[] result = null;
int smallIndex = 0;
int bigIndex = array.length - 1;
while (smallIndex < bigIndex) {
int currentSum = array[smallIndex] + array[bigIndex];
if (currentSum == sum) {
result = new int[2];
result[0] = array[smallIndex];
result[1] = array[bigIndex];
break;
} else if (currentSum < sum) {
smallIndex++;
} else {
bigIndex--;
}
}
return result;
}
/**
* 输入一个正数sum,打印出所有和为sum的连续正数序列(序列中最少2个数字)。
*
* 思路:
* 1)定义两个指针:第一个指针small指向序列的第一个元素(即最小元素),第二个指针big指向序列的最后一个元素(即最大元素)。
* 2)small默认指向1,big默认指向2。
* 3)若序列的和(small~big之间的数的和)大于sum,则将序列中的最小值去掉,即small向后移动,一直移动到序列的和不大于sum。
* 4)若序列的和(small~big之间的数的和)小于sum,则将序列中的最大值增大,即big向后移动,一直移动到序列的和不小于sum。
* 5)若序列的和(small~big之间的数的和)等于sum,则将序列打印出来,然后将big向后移动,继续寻找其它和为sum的序列。(big向后移动后,序列的和就大于sum了,故此时又进入到第3步)
* 6)序列中最少有两个数字且和为sum,故序列的第一个元素一定小于(sum+1)/2,所以当small不小于(sum+1)/2时,所有和为sum的序列都已经被打印过了。
*
* @param sum
*/
public static void printContinuousNumbersWithSum(int sum) {
if (sum < 3) return;
int small = 1;
int big = 2;
// 序列中最少有两个数字且和为sum,故序列的第一个元素一定小于(sum+1)/2
int half = (sum + 1) / 2;
int currentSum = small + big;
while (small < half) {
if (currentSum == sum) {
printContinuousNumbers(small, big);
} else {
// currentSum > sum 将small向后移动,直到currentSum不大于sum
while (currentSum > sum && small < half) {
currentSum = currentSum - small;
small++;
if (currentSum == sum) printContinuousNumbers(small, big);
}
}
/**
* 两种情况会执行下面代码:
* 1)currentSum < sum 将big向后移动,直到currentSum不小于sum
* 2)currentSum == sum 且 已经将序列打印了,故big继续向后移动,继续寻找和为sum的序列。
*/
big++;
currentSum = currentSum + big;
}
}
public static void printContinuousNumbers(int start, int end) {
for (int i = start; i <= end ;i++) {
System.out.print(i);
}
System.out.println();
}
public static void main(String[] args) {
// int[] array = {1, 2, 4, 7, 11, 15};
// int[] numbers = getNumbersWithSum(array, 15);
// System.out.println(Arrays.toString(numbers));
printContinuousNumbersWithSum(15);
}
}