剑指offer-41-和为s的两个数字VS和为s的连续正数序列-java

题目及测试

package sword041;
/* 
题目一:输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。假设有多个数字的和等于s,输出随意一对就可以。

比如输入数组{1,2,4,7,11,15}和数字15.因为4+11=15。因此输出4和11.

题目二:输入一个正数s,打印出全部的和为s的连续正数序列(至少含有两个数字)。

比如输入15。因为1+2+3+4+5=4+5+6=7+8=15,所以结果打印出3个连续的序列1——5,4——6。7——8.

*/

import java.util.List;

public class main {
	
	public static void main(String[] args) {
		int[][] testTable = {
   
   {1,2,4,7,11,15},{-1,-100,3,99}};
		int[] testTable2={15,1};
		for (int i=0;i<testTable.length;i++) {
			test(testTable[i],testTable2[i]);
		}
		
		int[] testTable3 = {15,10,6};
		for (int ito : testTable3) {
			test2(ito);
		}
	}
		 
	private static void test(int[] ito,int ito2) {
		Solution solution=new Solution();
		long begin = System.currentTimeMillis();
		for (int i = 0; i < ito.length; i++) {
		    System.out.print(ito[i]+" ");		    
		}
		System.out.println();
		//开始时打印数组
		System.out.println(ito2);
		
		System.out.println( "rtn=" );
		solution.findNumbersWithSum(ito,ito2);//执行程序
		long end = System.currentTimeMillis();	

		System.out.println();
		System.out.println("耗时:" + (end - begin) + "ms");
		System.out.println("-------------------");
	}
	
	private static void test2(int ito) {
		Solution solution = new Solution();
		long begin = System.currentTimeMillis();
		System.out.print(ito);		    
		System.out.println();
		//开始时打印数组
		
		System.out.println( "rtn=" );
		solution.findContinuousSequence(ito);//执行程序
		long end = System.currentTimeMillis();			

		System.out.println();
		System.out.println("耗时:" + (end - begin) + "ms");
		System.out.println("-------------------");
	}

}

题目1(成功)

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

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

很多人会立即能想到O(n2)的方法,也就是先在数组中固定一个数字,再依次判断数组中其余n-1个数字与它的和是不是等于s。

接着我们寻找更好的算法。我们先在数组中选择两个数字,如果他们的和等于输入的s,我们就找到了要找的两个数字。如果小于s呢?我们希望两个数字的和再大一点。由于数组已经排好序了,我们可以考虑选择较小的数字后面的数字。因为排在后面的数字要大一点,那么这两个数字的和也要大一点,就有可能等于输入的数字s了。同样,当两个数字的和大于输入的数字的时候,我们就可以选择较大的数字前面的数字了,因为排在前面的数字要小一些。

题目2(成功)

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

有了前面的经验,我们也考虑用两个树small和big分别表示序列的最小值和最大值。首先把small初始化为1,big初始化为2.如果从small到big的序列的和大于s,我们可以从序列中去掉较小的值,也就是增大small的值。如果从small到big的序列的和小于s,我们可以增大big,让这个序列包含更多的数字。因为这个序列至少要有两个数字,我们一直增加small 到(1+s)/2为止。

package sword041;


class Solution {
    public void findNumbersWithSum(int[] nums, int k) {
        int length=nums.length;
        if(length==0 || length == 1){
        	return;
        }
        int begin = 0;
        int end = length -1;
        while(begin <= end) {
        	int sum = nums[begin] + nums[end];
        	if(sum == k) {
        		System.out.println(nums[begin] + " "+ nums[end]);
        		return;
        	}
        	if(sum > k) {
        		end--;
        	}else {
        		begin++;
        	}
        }        
    }
    
    public void findContinuousSequence(int k) {
    	if(k <= 2) {
    		return;
    	}
        int begin = 1;
        int end = 2;
        int sum = 3;
        while(begin <= end && end <= k) {
        	if(sum == k) {
        		if(begin != end) {
        			System.out.println(begin + " "+ end);	
        		}
        		end++;
        		sum+=end;
        		continue;
        	}
        	if(sum > k && begin != end) {        		
        		sum-=begin;
        		begin++;
        	}else {
        		end++;
        		sum+=end;
        	}
        }
           
    }
}

猜你喜欢

转载自blog.csdn.net/xushiyu1996818/article/details/112170210