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

题目一:输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得它们的和正好是S。如果有多对数字的和等于S,输出任意一对即可。例如:输入数组{1,2,4,7,11,15}和数字15,输出应该是4和11.

思路分析:看到这个题最开始我就想到了,从该数组的第一个数字开始固定数字,求该数字和其余的n-1个数字之和,找到S即可,但是这个方法的时间复杂度是O(n^2).

有一种简单的思想,我们可以定义连个指针,一个指针指向该数组的第一个元素(a),一个指针指向该数组的最后一个元素(b),有以下三步:

(1)当a+b=S时,返回a和b即可;

(2)当a+b>S时,b往前挪一个位置;

(3)当a+b<S时,a往前挪一个位置。

还是使用上述的例子,用下图来展示这样的一个过程:


代码实现如下:

1.

vector<int> FindNumbersWithSum(vector<int> array, int sum)
{
	//先看类型,然后我们定义一个对应的值来作为返回值
	vector<int> result;
	int length = array.size();

	if (length <= 1 || sum <= 0)
		return result;

	//a为数组的第一个数,b为数组的最后一个数
	int a = 0;
	int b = length - 1;

	while (a<b)
	{
		int cursum = array[a] + array[b];
		if (cursum == sum)
		{
			result.push_back(array[a]);
			result.push_back(array[b]);
			break;
		}
		else if (cursum>sum)
		{
			b--;
		}
		else
		{
			a++;
		}
	}
	return result;
}

2.

bool FindNumbersWithSum(int data[], int length, int sum, int* num1, int* num2)
{
	bool found = false;
	if (length <= 1 || num1 == NULL || num2 == NULL)
		return found;

	int a = 0;//a在该数组的前面,从前往后
	int b = length - 1;//b在该数组的最后面,从后往前

	while (b > a)
	{
		int c = data[a] + data[b];
		if (c == sum)
		{
			*num1 = data[a];
			*num2 = data[b];
			found = true;
			break;
		}
		else if (c > sum)
		{
			b--;
		}
		else
		{
			a++;
		}
	}

	return found;
}

题目二:输入一个整数S,打印出所有和为S的连续整数序列(至少含有两个数字)。例如:输入15,由于1+2+3+4+5=4+5+6=7+8=15,因此,打印的结果有三对1~5、4~6、7~8.

思路分析:这个题和上题有相似之处,我们可以定义连个数,一个为small,一个为big,标记第一个数和第二个数,同样有以下三种情况:

(1)当该序列的和等于S时,将该连续序列打印出来;

(2)当该序列的和大于S时,big++;

(3)当该序列的和小于S时,small++.

说明:可能有人会问,那这个题的循环条件结束是什么呢?我们以S为15举例,和为S 的最大连续序列为7和8,也就是说8之后和为S 没有连续的序列了,因此,类比,可以知道,该循环结束的标志是small=(1+S)/2

下面我们用代码实现:

1.

vector<vector<int> > FindContinuousSequence(int sum) 
    {
        vector<vector<int> > result;
        if(sum<3)
            return result;
        
        int small=1;
        int big=2;
        int mid=(1+sum)/2;
        
        while(small<mid)
        {
            int cursum = 0;
            for(int i = small; i <= big; i++)
            {
                cursum += i;
            }
            if(cursum == sum)
            {
                vector<int> v;
                for(int i = small; i <= big; i++)
                {
                    v.push_back(i);
                }
                result.push_back(v);
                small++;
                big++;
            }
            else if(cursum < sum)
            {
                big++;
            }
            else
            {
                small++;
            }
        }
        return result;
    }

2.

void PrintSequence(int small, int big)
{
	for (int i = small; i <= big; i++)
	{
		cout << i;
	}
	cout << endl;
}


void FindSequence(int sum)
{
	if (sum <= 2)
		return;

	int small = 1;
	int big = 2;
	int mid = (1 + sum) / 2;
	int cursum = small + big;

	while (small < mid)
	{
		if (cursum == sum)
			PrintSequence(small, big);

		if (cursum > sum && small < mid)
		{
			cursum -= small;
			small++;

			if (cursum==sum)
				PrintSequence(small, big);
		}
		else
		{
			big++;
			cursum += big;
		}
	}
}

int main()
{
	int s = 15;
	int length = (s + 1) / 2;
	int *arr = new int[length];
	for (int i = 0; i < length-1; i++)
	{
		arr[i] = i + 1;
	}
	FindSequence( s);
	delete[] arr;

	cout << endl;
	return 0;
}
注意:当cursum>S时,先big++,然后再计算cursum的值;当cursum<S时,先计算cursum的值,再small++!


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值