题目描述:
输入一个正数s,打印出所有和为s的连续正数序列(至少含有两个数)。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序
例如输入15,由于1+2+3+4+5=4+5+6=7+8=15,所以结果打印出3个连续序列1~5、4~6和7~8。
样例:
输入:15
输出:[[1,2,3,4,5],[4,5,6],[7,8]]
分析:
初始化两个数small=1和big=2分别表示序列的最小值和最大值,
- 如果从small到big的序列和大于s,则可以去掉序列中最小的值,即增大small。
- 如果从small到big的序列和小于s,则可以增大big,让这个序列包含更多的数字。因为这个序列至少要包含两个数字,所以small一直增加到(1+s)/2为止。
- 如果从small到big的序列和等于s,则可以将该序列加入列表中,并令small++,重复前面的过程。
(这道题和上一道题都利用了序列单调递增这个性质)
public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {
ArrayList<ArrayList<Integer>> list=new ArrayList<>();
if(sum<=2)
return list;
int small=1,big=2;
int s=small+big;
while(small<(1+sum)/2) {
while(s<sum) {
big++;
s+=big;
}
while(s>sum) {
s-=small;
small++;
}
if(s==sum) {
ArrayList<Integer> l=new ArrayList<>();
for(int i=small;i<=big;i++)
l.add(i);
list.add(l);
s-=small;
small++;
}
}
return list;
}
第二种做法是利用等差数列的性质
//a,a+1,a+2,...a+n,序列的长度为n+1
//sum=(n+1)a+(n+1)n/2
public List<List<Integer> > findContinuousSequence1(int sum) {
List<List<Integer>> list=new ArrayList<>();
int n=1;
while(true) {
int x=n*(1+n)/2;
int m=sum-x;
if(m<0)
break;
int d=-1;
if(m%(n+1)==0) {
d=m/(n+1);
if(d!=0) {
List<Integer> l=new ArrayList<>();
for(int i=1;i<=n+1;i++) {
l.add(d);
d++;
}
list.add(l);
}
}
n++;
}
return list;
}