(剑指Offer)面试题41:和为s的连续正数序列
题目:
输入一个正数s,打印出所有和为s的连续正数序列(至少含有两个数)。例如输入15,由于1+2+3+4+5=4+5+6=7+8=15,所以结果打印出3个连续序列1-5,,4-6和7-8.
思路:
题目求的是连续正数序列,而且至少含有两个数,那么我们可以从1,2这两个数开始,
以求和为9的所有连续序列为例,假设两个指针pSmall和pBig,分别指向正数序列的首尾,pSum表示序列之和,一开始pSmall=1,pBig=2,,pSum=3<9,序列需要包含更多的数,于是pBig+1,此时pSum=6,依旧小于9,于是pBig+1,此时pSum=10,大于9,序列需要删除一些数,于是pSmall-1,pSum=9,找到第一个满足条件的序列;接着pBig+1,按照前面的方法继续查找满足条件的序列,直到pSmall等于(s+1)/2.
代码:
#include <iostream> #include <vector> using namespace std; void PrintContinuousSequence(int pSmall,int pBig){ for(int i=pSmall;i<=pBig;i++) cout<<i<<" "; cout<<endl; } void FindContinuousSequence(int sum){ if(sum<3) return; int pSmall=1; int pBig=2; int halfSum=((sum+1)>>1); int curSum=pSmall+pBig; while(pSmall<halfSum){ if(curSum==sum) PrintContinuousSequence(pSmall,pBig); while(curSum>sum && pSmall<pBig-1){ curSum-=pSmall; pSmall++; if(curSum==sum) PrintContinuousSequence(pSmall,pBig); } pBig++; curSum+=pBig; } } int main() { FindContinuousSequence(3); return 0; }
在线测试OJ:
http://www.nowcoder.com/books/coding-interviews/c451a3fd84b64cb19485dad758a55ebe?rp=2
小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!
输出描述:输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序
AC代码:
class Solution { public: vector<vector<int> > FindContinuousSequence(int sum) { vector<vector<int> > result; if(sum<3) return result; int pSmall=1; int pBig=2; int curSum=pSmall+pBig; int halfSum=((sum+1)>>1); vector<int> sequence; while(pSmall<halfSum){ if(curSum==sum){ GetSequence(pSmall,pBig,sequence); result.push_back(sequence); } // at least two numbers while(curSum>sum && pSmall<pBig-1){ curSum-=pSmall; pSmall++; if(curSum==sum){ GetSequence(pSmall,pBig,sequence); result.push_back(sequence); break; } } pBig++; curSum+=pBig; } return result; } void GetSequence(int pSmall,int pBig,vector<int> &sequence){ sequence.clear(); for(int i=pSmall;i<=pBig;i++) sequence.push_back(i); } };