和为s的两个数字VS和为s的连续正数序列(Java)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013132035/article/details/82052376

题目:

输入一个递增排序的数组和一个数字s,在数组在查找两个数,使得它们的和正好是。如果有多对数字的和等于s,输出任意一对即可。

例如:输入数组{1、2、4、7、11、15}和数字15。由于4 + 11 = 15,因此输出4 和 11。

思路:

直观的思路:遍历数组两遍,即每一个数字和后面的数字相加看是否等于15,是直接返回,否则继续遍历直到找到或者遍历结束为止。时间复杂度O(n^2)。

最优解思路:定义两个指针p1和p2,p1指向1,p2指向15。p1 + p2 大于15,p2指针移动,p1 + p2 小于15,p1指针移动,直到p1 + p2 = 15,返回p1和p2。

代码实现:

public static ArrayList<Integer> findNumbersWithSum(int data[], int sum){
	ArrayList<Integer> list = new ArrayList<Integer>();
	if(data == null || data.length < 2){
		return list;
	}
	int p1 = 0; //指向数组首元素
	int p2 = data.length - 1; //指向数组末尾元素
	while(p2 > p1){
		if(data[p1] + data[p2] == sum){
			list.add(p1);
			list.add(p2);
		}else if(data[p1] + data[p2] > sum){
			p2--;
		}else{
			p1++;
		}
	}
	return list;
}

拓展题目:

输入一个整数s,打印出所有和为s的连续正数序列(至少含有两个数)。例如输入15,由于1 + 2 + 3 + 4 + 5 = 4 + 5 + 6 = 7 + 8 =15,所以结果打印出3个连续序列1~5,4~6和7~8。

思路:

定义两个指针p1和p2分别指向数组的第一个位置和数组的第二个位置,求序列的和,如果小于s,p2向后移动,继续就和,如果满足,打印当前p1和p2指向的序列片段,p2继续移动,此时序列的和会大于s,p1向前移动,判断序列和是否为s,如果小于s,p2向后移动,继续上面的判断,否则如果大于s,p1向前移动,在判断和,如果大于或者等于,或者小于,分别做对应的处理。等于的话:输出序列片段,p2向后移动;小于的话p2直接向后移动,再做判断;大于的话p1向后移动,再做判断。

代码实现:

public static ArrayList<ArrayList<Integer>> finfContinuousSequence(int sum){
	ArrayList<ArrayList<Integer>> list = new ArrayList<ArrayList<Integer>>();
	if(sum < 3){ //因为至少含有两个数,故1+2=3,故sum > 3
		return list;
	}
	ArrayList<Integer> l = new ArrayList<Integer>();
	int small = 1;
	int big = 2;
	int middle = (1 + sum) / 2; //因为至少连续2个且顺序增加,所以取中间值
	int curSum = small + big;
	while(small < middle){
		if(curSum == sum){
			for(int i = small; i <= big; i++){
				l.add(i);
			}
			list.add(l);
		}
		while(curSum > sum && small < middle){
			curSum -= small;
			small++;
			if(curSum == sum){
				for(int i = small; i <= big; i++){
					l.add(i);
				}
				list.add(l);
			}
		}
		big++;
		curSum += big;
	}
	return list;
}

猜你喜欢

转载自blog.csdn.net/u013132035/article/details/82052376