和为S的两个数字 & 和为S的连续正数序列
2017-06-14 18:21
295 查看
一. 和为S的两个数字
题目:
输入一个递增排序的数组和一个数字S,在数组中查找两个数,是的他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。解题思路:
1.定义两个指针,分别指向第一个数字和最后一个数字;2.如果两个指针所指向的数的和等于S, 如果这两个数的乘积小于之前找到的结果就替换掉旧的结果;
3.如果两个指针所指向的数的和大于S,则第二个指针减减;
4.如果两个指针所指向的数的和小于S,则第一个指针加加;
java实现:
import java.util.ArrayList; public class Solution { public ArrayList<Integer> FindNumbersWithSum(int [] array,int sum) { ArrayList<Integer> res = new ArrayList<Integer>(); int minVal = Integer.MAX_VALUE; int num1 = Integer.MIN_VALUE; int num2 = Integer.MAX_VALUE; int i = 0, j = array.length - 1; while(i < j){ if(array[i] + array[j] == sum){ if(array[i] * array[j] < minVal){ minVal = Math.min(minVal, array[i] * array[j]); num1 = array[i]; num2 = array[j]; } i++; j--; }else if(array[i] + array[j] < sum){ i ++; }else{ j --; } } if(num1 + num2 == sum){ res.add(num1); res.add(num2); } return res; } }
二. 和为S的连续正数序列
题目:
输入一个正数s,打印出所有和为s的连续整数序列(至少含有两个数)。例如输入15,由于1+2+3+4+5=4+5+6=7+8=15,所以结果打印出3个连续序列1~5、4~6和7~8。注:美团暑期实习1面问到了这个题
解题思路:
解法一:数学解法
解题思路:
设有a个连续的正整数,从b(b>0)开始,和为S。b + b + 1 + b + 2 + … + b + a -1 = S
ab + a(a-1)/2 = S
a(2b + a - 1) = 2S
因为a,b属于整数,所以2S能整除a
所以枚举2S的约数记为a,时间复杂度O(S‾√),b=1/2(2N/a+1-a),判断b是否属于整数,时间复杂度O(1)。
java实现:
import java.util.ArrayList; public class Solution { public ArrayList<ArrayList<Integer>> FindContinuousSequence(int sum) { ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>(); for(int a = 2; a * a < 2 * sum; a ++){ //有a个连续的整数 if(2*sum % a == 0){//a是2*sum的约数 if((2*sum + a - a*a) / (2 * a) > 0 && (2*sum + a - a*a) % (2 * a) == 0){ ArrayList<Integer> al = new ArrayList<Integer>(); for(int i = (2*sum + a - a*a) / (2 * a); i < ((2*sum + a - a*a) / (2 * a) + a); i ++){ al.add(i); } res.add(0, al); } } } return res; } }
解法二:
解题思路:
1.用两个整数small和big分别表示序列的最小值和最大值,small初始化为1,big初始化为2。2.如果从small到big的和大于s,从序列中去掉最小值,即增大small的值。
3.如果从small到big的和小于s,增大big,让这个序列包含更多的数字,因为至少含有两个数字。
4.如果从small到big的和等于s,打印,之后增大big。
5.small增加到(1+sum)/ 2为止。
本题技巧:
通常我们用循环求一个连续序列的和,但考虑到每一次操作之后的序列和操作之前的序列相比大部分数字都是一样的,只是增加或者减少了一个数字,因此,本题在前一个序列的和的基础上求操作之后的序列的和。减少了不必要的运算,提高了代码的效率。java实现:
b725 import java.util.ArrayList; public class Solution { public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) { ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>(); int small = 1, big = 2; int curSum = small + big; while(small < ((sum + 1) / 2)){ if(curSum <= sum){ if(curSum == sum){ ArrayList<Integer> list = new ArrayList<Integer>(); int i = small; while(i <= big){ list.add(i); i ++; } res.add(list); } big ++; curSum += big; } else { curSum -= small; small ++; } } return res; } }
相关文章推荐
- 41.和为s的两个数字&和为s的连续正数序列
- 找逆序的对数&&和为n的两个数字&&和为n的连续正数序列
- 和为n连续正数序列 & 排序数组中和为给定值的两个数字
- 和为S的两个数字之和&&和为s的连续正数序列
- 和为s的两个数字&&和为s的连续正数序列
- [剑指offer][面试题41]和为s的两个数字 VS 和为s的连续正数序列
- 和为s的两个数字 VS 和为s的连续正数序列
- 剑指offer 面试题41—和为s的两个数字VS和为s的连续正数序列
- 和为S的两个数字 VS 和为S的连续正数序列
- 【剑指offer-Java版】41和为s的两个数字VS和为s的连续正数序列
- 剑指offer 41 - 和为s的两个数字VS为s的连续正数序列
- 41.和为s的两个数字VS和为s的连续正数序列
- 剑指offer——和为s的两个数字VS和为s的连续正数序列
- 【面试题041】和为s的两个数字VS和为s的连续正数序列
- 剑指Offer之 - 和为s的两个数字 VS 和为s的连续正数序列
- 剑指offer---和为s的两个数字VS和为s的连续正数序列
- 和为S的两个数字VS和为s的连续正数序列
- 面试算法(四十一)和为s的两个数字VS和为s的连续正数序列
- 【剑指offer】6.3知识迁移能力——面试题41:和为s的两个数字VS和为s的连续正数序列
- 面试题41:和为s的两个数字VS和为s的连续正数序列