输入一个正数n,输出所有和为n 连续正数序列

来源:互联网 发布:非凸优化 编辑:程序博客网 时间:2024/03/29 23:33
题目:

输入一个正数n,输出所有和为n 连续正数序列。

例如输入15 = 1+2+3+4+5 = 4+5+6 = 7+8.

这道题不难,通常首先想到的方法是两个for循环,逐个寻找从i到j的和为n的序列,代码如下:

int sum(int i, int j){return (i + j) * (j - i + 1) / 2;}void SumN(int n){for (int i = 1; i < n; ++i){for (int j = i + 1; j < n; ++j){if (sum(i, j) == n)cout << i << "-" << j << endl;}}}

思路很简单,但是循环里有很多重复计算,例如计算1-3时就重复计算了1-2,时间复杂度为n*n.设置一个头节点和一个尾节点,仔细观察题目不难得知和只跟序列头和尾有关,以某个头节点开始的序列和等于n的最多只有一个。当序列和小于n时,应该加入下一个大的尾;当序列和大于n时,应该弹出头节点;当序列和等于n时,输出,并弹出头节点以计算下一个序列。这样我们可以使用一个双端队列来存储序列,序列和小于n时,在队列尾部插入下一个节点;序列和大于n时,在队列头部弹出头节点;序列和等于n时,输出结果,然后弹出队列头节点以计算下一个序列。当节点到达n时,结束。

void SumN(int n){deque<int> sequence;int i = 1;int res = 0;while (i < n){if (res < n){sequence.push_back(i);res += i++;}else if (res > n){res -= sequence.front();sequence.pop_front();}else{cout << sequence.front() << "-" << sequence.back() << endl;res -= sequence.front();sequence.pop_front();}}}




0 0
原创粉丝点击