剑指Offer面试题(第三十三天)面试题57(1)、57(2)

 * 面试题57:和为s的数字


     * 题目一:和为s的两个数字


     * 输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得他们的和正好是s。
     * 如果有多对数字的和等于s,则输出任意一对即可。
     * 例如:输入数组{1,2,4,7,11,15}和数字15,由于4+11=15,因此输出4和11
     *
     * 
     * 思路:
     * 方法一:时间复杂度O(n2)
     * 首先固定一个数字,然后和剩余的n-1个数字进行求和,判断其和是否等于s
     * 
     * 方法二:时间复杂度O(n)
     * 首先选取两个指针:一个指向首部,一个指向尾部, 因为是一个递增排列的有序序列,所以可以
     * 然后对两个指针指向的数字进行求和,判断是否等于s:
     * 1>若等于s,则找到和为s的两个数字
     * 2>若小于s,则将第一个指针向后移动,使其指向更大的数字,然后再接着判断其和是否等于s
     * 3>若大于s,则将第二个指针向前移动,使其指向稍小的数字,然后再接着判断其和是否等于s,
     * 不断重复上诉过程直到第一个指针和第二个指针指向同一个数字为止
 

package Test;

public class No57First_FindNumbersWithSum {

	/*
	 * 面试题57:和为s的数字
	 * 题目一:和为s的两个数字
	 * 输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得他们的和正好是s。
	 * 如果有多对数字的和等于s,则输出任意一对即可。
	 * 例如:输入数组{1,2,4,7,11,15}和数字15,由于4+11=15,因此输出4和11
	 *
	 * 
	 * 思路:
	 * 方法一:时间复杂度O(n2)
	 * 首先固定一个数字,然后和剩余的n-1个数字进行求和,判断其和是否等于s
	 * 
	 * 方法二:时间复杂度O(n)
	 * 首先选取两个指针:一个指向首部,一个指向尾部, 因为是一个递增排列的有序序列,所以可以
	 * 然后对两个指针指向的数字进行求和,判断是否等于s:
	 * 1>若等于s,则找到和为s的两个数字
	 * 2>若小于s,则将第一个指针向后移动,使其指向更大的数字,然后再接着判断其和是否等于s
	 * 3>若大于s,则将第二个指针向前移动,使其指向稍小的数字,然后再接着判断其和是否等于s,
	 * 不断重复上诉过程直到第一个指针和第二个指针指向同一个数字为止
	 * 
	 * 
	 * 
	 * 
	 * */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		No57First_FindNumbersWithSum f = new No57First_FindNumbersWithSum();
		int[] array = {1,2,4,7,11,14};
		int sum = 15;
		int[] twoNumbers = f.FindNumbersWithSum(array,sum);
		System.out.println("和为"+sum+"的两个数字分别是;"+twoNumbers[0]+" 和 "+twoNumbers[1]);
	}

	
	private int[] FindNumbersWithSum(int[] array, int sum) {
		// TODO Auto-generated method stub\
		int[] result = new int[2];
		
		if(array == null || array.length == 0 || sum <= 3)
			return null;
		
		int start = 0;
		int end = array.length - 1;
		while(start < end) {
			if(array[start] + array[end] == sum) {
				result[0] = array[start];
				result[1] = array[end];
				break;
			}
			else if(array[start] + array[end] < sum) {
				start++;
			}
			else
				end--;
		}
		
		return result;
	}

}

 * 面试题57:和为s的数字


     * 题目二:和为s的连续正数序列


     * 输入一个正数s,打印出所有何为s的连续正数序列(至少含有两个数)。
     * 例如:输入15,由于1+2+3+4+5 = 4+5+6 =7+8 = 15
     * 所以要打印出3个连续序列1~5、4~6、7~8
     * 
     * 思路; 可以根据上一个题目的思路继续探究:以s = 9为例 
     * 设置两个指针,一个指针指向最小值,一个指针指向最大值,
     * 初始值一个为1,一个为2 ,相加等于3,小于s,则增大big,
     * 判断序列{1,2,3}相加与s的关系,若小于则继续增大big,
     * 判断序列{1,2,3,4}相加与s的关系,若大于则增大small,
     * 判断序列{2,3,4}相加与s的关系,相等,则打印,并且增大big
     * 判断序列{2,3,4,5}相加与s的关系,大于,则增大small,
     * 判断序列{3,4,5}相加与s的关系,大于,则增大small,
     * 判断序列{4,5}相加与s的关系,相等,则打印,
     * 综上所述:
     * 当序列{a,b,c,d,...}当其和的值等于s,zedayin
     * 当其和的值小于s,增大big,让序列包含更多的值
     * 当其和的值大于s,增大small,让序列包含更少的值
     * 
     * 也就相当于在和小于s时,一直进行big++
     * 直到大于等于s以后停止增加big,
     * 若等于则打印;
     * 若大于则增加small,减少序列之和,以求出等于s的序列

package Test;

public class No57Second_FindContinuousSequence {

	/*
	 * 面试题57:和为s的数字
	 * 题目二:和为s的连续正数序列
	 * 输入一个正数s,打印出所有何为s的连续正数序列(至少含有两个数)。
	 * 例如:输入15,由于1+2+3+4+5 = 4+5+6 =7+8 = 15
	 * 所以要打印出3个连续序列1~5、4~6、7~8
	 * 
	 * 思路; 可以根据上一个题目的思路继续探究:以s = 9为例 
	 * 设置两个指针,一个指针指向最小值,一个指针指向最大值,
	 * 初始值一个为1,一个为2 ,相加等于3,小于s,则增大big,
	 * 判断序列{1,2,3}相加与s的关系,若小于则继续增大big,
	 * 判断序列{1,2,3,4}相加与s的关系,若大于则增大small,
	 * 判断序列{2,3,4}相加与s的关系,相等,则打印,并且增大big
	 * 判断序列{2,3,4,5}相加与s的关系,大于,则增大small,
	 * 判断序列{3,4,5}相加与s的关系,大于,则增大small,
	 * 判断序列{4,5}相加与s的关系,相等,则打印,
	 * 综上所述:
	 * 当序列{a,b,c,d,...}当其和的值等于s,zedayin
	 * 当其和的值小于s,增大big,让序列包含更多的值
	 * 当其和的值大于s,增大small,让序列包含更少的值
	 * 
	 * 也就相当于在和小于s时,一直进行big++
	 * 直到大于等于s以后停止增加big,
	 * 若等于则打印;
	 * 若大于则增加small,减少序列之和,以求出等于s的序列
	 * 
	 * */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		No57Second_FindContinuousSequence f = new No57Second_FindContinuousSequence();
		int sum = 9;
		System.out.println("和为s的连续正数序列:");
		f.FindContinuousSequence(sum);
	}

	//求连续序列
	private void FindContinuousSequence(int sum) {
		// TODO Auto-generated method stub
		if(sum < 3)
			return;
		int small = 1;
		int big = 2;
		//curSum记录当前和
		int curSum = small + big;
		int mid = (1+sum)/2;
		
		while(small < mid) {
			
			if(curSum == sum)
				PrintContinuousSequence(small,big);
			
			//若当前值大于s,则删去small当前值,并将small++  
			//然后判断curSum是否等于
			while(curSum > sum && small < mid) {
				curSum -= small;
				small++;
				
				if(curSum == sum)
					PrintContinuousSequence(small,big);
			}
			
			big++;
			curSum += big;
			
		}
	}

	//打印序列
	public void PrintContinuousSequence(int small, int big) {
		for(int i = small;i <= big;i++)
			System.out.print(i+" ");
		System.out.println();
	}
}

猜你喜欢

转载自blog.csdn.net/weixin_43137176/article/details/89764775