有序数组中和为定值的数字对与和为定值的连续正整数序列
首先,对于这样的连续序列一般情况下我们是不会选择双层循环遍历的方式的。原因十分简单这个对时间复杂度的优化太差了。那么我们对于这样的定值和连续序列的问题怎办呢?
我们从题目中可以获取一个很重要的信息,就是对于我们的正整数序列,其实也是有顺序的。这样我们就有一部分头绪了。这里我们先讨论第一个问题,都是对于定位的运用。因为数组是有序的,我们可以假设数组是升序的。对于和为定值的情况,我们,从数组的收尾两头开始各定位一个数字,然后继续下来计算当前两个数字的和,如果和大于给定的定值,那么我们就可以把右边定位数字的位置向左移动,这样和就会变小,然后判断当前和 与 给定定值的大小,如果当前和大于给定值,就右边的位置向左,如果当前和小于给定值,我们就把左边的位置向右移动。我们找思路来看图,假定给定值是13,我们开始位置在开头和末尾。
我们发现两个数字的和小于我们的给定值13,那我们的左边向右移动
和等于我们的给定值了,这个时候输出我们的数字对,
接下左边继续向右移动。发现数字和大于给定值,我们右边左移动,
这样我们的所有和为定值的数据对,就可以在一遍遍历的情况下全部找出来了。
然后,看我们的下一个问题就是和为定值的连续正整数序列。数列开始的序列是1,2 然后我们和给定的值进行比较,如果大于给定的值,这个时候我们去掉最左边的数字,接下来和给定值比较,如果比给定值小,就从右边引入连续的数字,如果值和给定值一样我们就可以输出序列。然后继续从右边引入值。是不是和我们的上面比较类似。都是两个指标,只不过上面的指标,是反方向运动。不过这次的指标是相同的方向运动了呢!
接下来给出相应的代码。
首先,是第一题的代码
`package bj.blog;
/**
* 本类主要解决一下一个问题,
* 问题描述如下:计算出一个有序数组中的所有和为定值的数字对
* 目前代码中假设数组是升序的,如果是降序可以类似处理.
*/
public class SumIsGivenValueDigitalPairs {
public static void main(String[] args) {
int[] array = new int[]{1,1, 2, 3, 4, 5, 5, 6, 6};
// sumIsGivenValueDigitalPairs(7,array);
sumIsGivenValueDigitalPairsSame(7, array);
}
/**
* @param sum 给定的和
* @param array 给定数组中,从这个数组里面找相应的数据对
* 不考虑,相同数字情况
*/
public static void sumIsGivenValueDigitalPairs(int sum, int[] array) {
if (array.length < 2) {
return;
}
int start = 0;
int end = array.length - 1;
while (start < end) {
if (array[start] + array[end] > sum) {
end–;
continue;
}
if (array[start] + array[end] < sum) {
start++;
continue;
}
if (array[start] + array[end] == sum) {
System.out.print(“Pairs ” + array[start]);
System.out.println(“\t” + array[end]);
//因为不考虑数字相同的情况,所以我们可以采取左边的坐标向右移动,也可以采用右边的坐标向左移动
start++;
}
}
}
/**
* @param sum 给定的和
* @param array 给定数组中,从这个数组里面找相应的数据对
* 考虑,相同数字情况
* 如果考虑数字相同,但是认为数字相同但数组下标不同就认为是不同的数字对,
* 数组1,1,2,3,4,5,5,
* 就是认为第一个1和第二1是不同的
*/
public static void sumIsGivenValueDigitalPairsSame(int sum, int[] array) {
if (array.length < 2) {
return;
}
int start = 0;
int end = array.length - 1;
boolean leftToRight = true;
while (array[start] + array[end] == sum && start < end) {
int first = start;
boolean leftSame = false;
while (array[start] == array[first+1]) {
//因为有重复所以输出两次
first++;
for(int i = 0; i < 2; i++) {
System.out.print("Pairs " + array[end] + "\t");
System.out.println(array[start]);
}
leftSame = true;
}
int second = end;
boolean rightSame = false;
while (array[end] == array[second-1]) {
rightSame = true;
second--;
for(int i = 0; i < 2; i++) {
System.out.print("Pairs " + array[end] + "\t");
System.out.println(array[start]);
}
}
if(leftSame) {
start = first + 1;
}else {
start = first;
}
if(rightSame) {
end = second - 1;
}else {
end = second;
}
//输出数组头和尾加起来等于给定值的情况
}
while (start < end) {
if (array[start] + array[end] > sum) {
end--;
leftToRight = false;
continue;
}
if (array[start] + array[end] < sum) {
start++;
leftToRight = true;
continue;
}
if (array[start] + array[end] == sum) {
System.out.print("Pairs " + array[start]);
System.out.println("\t" + array[end]);
if (leftToRight) {
start++;
} else {
end--;
}
}
}
}
}
package bj.blog;
接下来是第二题代码:
/**
* 求和为定值的正整数序列
*/
public class SumIsGivenValueQueue {
public static void main(String[] args) {
sumIsGivenValueQueue(21);
}
public static void sumIsGivenValueQueue(int sum) {
int start = 1;
int end = 2;
int sumTemp = 3;
while (end <= sum / 2 + 1 && start < end) {
sumTemp = (start + end) * (end - start + 1) / 2;
if (sum == sumTemp) {
for (int i = 0; i < end -start + 1; i++) {
System.out.print((start + i) + "\t");
}
System.out.println("sumTemp = " + sumTemp);
end++;
}
if (sumTemp < sum) {
end++;
}
if (sumTemp > sum) {
start++;
}
}
}
}
`最后文章尾部,附上GitHuGitHub地址https://github.com/yunzhifei/mavenalgorithm.git