题目:小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!
输出描述:
输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序
解法,刚开始直接用的暴力解法,解题思路是通过遍历在100/i附近对数字进行拼接,如果100%i==0,那连续正数数列肯定在100/i处附近对称,如果100%i!=0,那肯定左边或者右边会多出一个数,解法如下:
import java.util.*;
public class Solution {
public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {
ArrayList<ArrayList<Integer>> resultlist = new ArrayList<ArrayList<Integer>>();
int midnum = sum/2;
if(sum==3){
ArrayList<Integer> templist = new ArrayList<Integer>();
templist.add(1);
templist.add(2);
resultlist.add(templist);
return resultlist;
}
for(int i=2;i<midnum;i++){
int middle = sum/i;
if(sum%i==0){
int temp = 0;
for(int j=middle-i/2;j<=middle+i/2&&j>0;j++){
temp = temp+j;
}
if(temp==sum){
ArrayList<Integer> templist = new ArrayList<Integer>();
for(int j=middle-i/2;j<=middle+i/2;j++){
templist.add(j);
}
resultlist.add(templist);
}
}else{
int modNum = sum%i;
int max = sum - middle*(i-1);
int temp = 0;
if(max==modNum+middle&&middle+i/2==max){
ArrayList<Integer> templist = new ArrayList<Integer>();
for(int j=middle-i/2+1;j<=middle+i/2&&j>0;j++){
templist.add(j);
temp = temp + j;
}
if(templist!=null&&templist.size()!=0&&temp==sum){
resultlist.add(templist);
}
}
}
}
Collections.sort(resultlist,new MyComparator());
return resultlist;
}
class MyComparator implements Comparator{
public int compare(Object object1, Object object2) {// 实现接口中的方法
ArrayList<Integer> p1 = (ArrayList<Integer>) object1; // 强制转换
ArrayList<Integer> p2 = (ArrayList<Integer>) object2;
if(p1.get(0)>=p2.get(0)){
return 1;
}else{
return -1;
}
}
}
}
后来看了一下网友的解法,觉得更加巧妙,贴上来:
思路:
由,求和为s的的两个数得到的启发。
由于是要求连续的。所以我们就从左开始走。
当连续数组和小于sum时,我们肯定得再多加一点。那么就再加上后一个数字。(i++)
当所加和大于sum时,那么我们肯定得减小一点。舍弃第一个数字。
当所加和等于时,listAll添加一个新的list。然后list删去head,count减去head。
import java.util.ArrayList;
public class Solution {
public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {
ArrayList<ArrayList<Integer>> listALL = new ArrayList<>();
ArrayList<Integer> list = new ArrayList<>();
if (sum < 1) {
return listALL;
}
int count = 0;
int head = 0;
// 最多就到sum/2
for (int i = 1; i <= sum;) {
if (count < sum) {
count += i;
list.add(i);
i++;
} else if (count > sum) {
head = list.remove(0);
count -= head;
} else {
listALL.add(new ArrayList(list));
head = list.remove(0);
count -= head;
}
}
return listALL;
}
}