您的位置:首页 > 其它

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

2017-08-10 11:52 253 查看

问题一

题目

输入一个递增排序的数组和一个数字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;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: