题目描述
小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!
输出描述:
输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序
(1)最简单的思路,挨着查找
package xidian.lili.niuke;
import java.util.ArrayList;
public class Solution {
public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {
ArrayList<ArrayList<Integer> > lists=new ArrayList<ArrayList<Integer>>();
int target=sum;
for(int i=1;i<sum;i++){
if(ContinuousSequence(sum,i)!=null){
lists.add(ContinuousSequence(sum,i));
}
}
return lists;
}
private ArrayList<Integer> ContinuousSequence(int sum, int start) {
ArrayList<Integer> list=new ArrayList<Integer>();
for(int i=start;sum>=0;i++){
sum=sum-i;
list.add(i);
}
if(sum==0){
return list;
}
return null;
}
}
(2)根据求和公式,选取一个滑动窗口移动滑动窗口直到窗口和为sum,把窗口之间的数字加入list
import java.util.ArrayList;
public class Solution {
public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {
ArrayList<ArrayList<Integer> > lists=new ArrayList<ArrayList<Integer>>();
int start=1;
int end=2;
while(end>start){
int psum=(start+end)*(end-start+1)/2;
if(psum==sum){
ArrayList<Integer> list=new ArrayList<Integer>();
for(int i=start;i<=end;i++){
list.add(i);
}
lists.add(list);
start++;
}else if(psum<sum){
end++;
}else{
start++;
}
}
return lists;
}
}
(3)充分利用连续正整数求和公式,连续n个正整数的和是S
若n是奇数 平均值=S/n(n个正整数的中间值),所以条件是(n&1)==1 && sum%n==0
n是偶数 平均值=S/n,且为偶数,平均值的小数部分是0.5.也就是(S%n)/n=0.5,所以条件是 sum%n*2==n
且根据S=(1+n)*n/2从1开始求出n的取值范围 n<根号2S
import java.util.ArrayList;
public class Solution {
public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {
ArrayList<ArrayList<Integer> > lists=new ArrayList<ArrayList<Integer>>();
for(int n=(int) Math.sqrt(2*sum);n>=2;n--){
if((n&1)==1 && sum%n==0 || sum%n*2==n){
ArrayList<Integer> list=new ArrayList<Integer>();
for(int j=0,k=sum/n-(n-1)/2;j<n;j++,k++){
list.add(k);
}
lists.add(list);
}
}
return lists;
}
}