和为s的两个数字VS和为s的连续正数序列
2017-08-10 11:52
302 查看
问题一
题目输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得他们的和正好为s,如果有多对数字的和为s,输出任意一对即可。
例如:输入数组{1,2,4,5,11,15}和数字15,输出4和11。
分析
(1)最直观的解法,时间复杂度为O(n^2)
两个嵌套循环,
固定一个数字,然后再后面找另一个数字,看是否和为s。
(2)更快的解法,时间复杂度为O(n)
由于数组是排序递增的数组,那么找和为s的两个数字,可以从前面找一个小的,从后面找一个大的。
bool FindNumbersWithSum(int arr[], int len, int sum, int*num1, int *num2) { if (arr == NULL || len <= 0 || num1 == NULL || num2 == NULL) return false; //定义两个点,从前找小的,从后找大的 int begin = 0; int end = len - 1; while (begin < end) { int curSum = arr[begin] + arr[end]; if (curSum == sum) { *num1 = arr[begin]; *num2 = arr[end]; return true; } else if (curSum < sum) ++begin; else --end; } return false; }
问题二
问题输入一个正数s,打印出所有和为s的连续正数序列(至少含有两个正数)
例如输入15,1+2+3+4+5=4+5+6=7+8 = 15
分析
这个问题,比上一个问题,稍微难一些,但是借助上一问的思路,可以做出来。
定义两个数组,small和big,来作为序列的最小值和最大值。
初始化,samll = 1,big =2;
如果从small到big的序列的和大于s,那么就从序列中去掉最小值,增大samll的值,再比较序列中的和是否大于s。循环,直到小于s。
如果从small到big的序列和小于s,那么增大big,让序列包含更多的值。
因为序列至少两个数字,那么small增加到 (1+s)/2。
void PrintSequence(int small, int big) { for (int i = small; i <= big; ++i) { cout << i << " "; } cout << endl; } void FindContinuousSequence(int sum) { int small = 1; int big = 2; int mid = (1 + sum) / 2; int curSum = small + big; while (small < mid) { if (curSum == sum) PrintSequence(small, big); //接着再找 while (small < mid && curSum > sum) { curSum -= small; ++small; if (curSum == sum) PrintSequence(small, big); } ++big; curSum += big; } }
相关文章推荐
- 剑指Offer:和为s的两个数字VS和为s的连续正数序列
- 剑指offer 41. 和为s的两个数字VS和为s的连续正数序列
- 和为S的两个数字VS和为s的连续正数序列
- 剑指offer之面试题41和为s的两个数字VS和为s的连续正数序列
- 《剑指Offer》学习笔记--面试题41:和为s的两个数字VS和为s的连续正数序列
- 剑指offer:和为s的两个数字VS和为s的连续正数序列(java)
- 剑指Offer:和为 S 的两个数字 VS 和为 S 的连续正数序列
- 和为s的两个数字VS和为s的连续证正数序列
- 和为S的两个数字 VS 和为S的连续正数序列
- 【剑指Offer学习】【面试题41:和为s 的两个数字vs 和为s 的连续正数序列】
- 【面试题041】和为s的两个数字VS和为s的连续正数序列
- 剑指offer-面试题41-和为s的两个数字VS和为s的连续正数序列
- 和为s的两个数字 VS 和为s的连续正数序列
- 剑指offer41:和为s的两个数字VS和为s的连续正数序列
- Q41:和为s的两个数字VS和为s的连续正数序列
- 面试题41:和为s的两个数字 VS 和为s的连续正数序列
- 和为s的两个数字VS和为s的连续正数序列
- 和为S的两个数字VS和为S的连续正数序列
- 和为S的两个数字VS和为S的连续正数序列
- 和为s的两个数字VS和为s的连续正数序列