您的位置:首页 > 其它

和为S的连续正数序列

2016-06-24 16:24 281 查看

题目

输出所有和为S的连续正数序列(至少含有两个数),序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序

解题

和为S的数,只有一个数时候和为S,这个数就是S,当数多余两个的时候,序列中的值最大不会超过这个最大值S

换句话说:

求1到S内,和为S的连续正数序列

方法一:暴力

两点:

连续和,等差数列公式

判断和是否等于S

但是当S比较大的时候求连续和会越界

import java.util.ArrayList;
public class Solution {
public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {
ArrayList<ArrayList<Integer> > result = new ArrayList<ArrayList<Integer> >();
ArrayList<Integer> list = new ArrayList<Integer>();
for(int i = 1;i<=sum;i++){
for(int j=i+1;j<=sum;j++){
int s = getSum(i,j);
if(s == sum){
add(list,i,j);
result.add( new ArrayList<Integer>(list));
list.clear();
}
}
}
return result;
}
public void add(ArrayList<Integer> list,int i,int j){
if(i==j)
return;
for(int k=i;k<=j;k++)
list.add(k);
}
public int getSum(int i,int j){
int s = (i+j)*(j-i+1)/2;
return s;
}
}


上面程序还可以优化

当出现大于sum的情况后,j增加一定大于sum

增加判断条件

if(s == sum){
add(list,i,j);
result.add( new ArrayList<Integer>(list));
list.clear();
}else if(s<0 ||s > sum){
break;
}


s<0 说明越界了,越界不符合条件,因为sum是Integer

s>sum 不符合条件以后的数也不符合条件

讨论中看到下面的求解

设这个序列的边界是:a、b

(a+b)(b−a+1)=2∗Sum(a+b)(b-a+1) = 2*Sum

x=a+bx = a+b

y=b−a+1y = b-a+1

x+y=2b+1x +y= 2b+1

x−y=2a−1x -y = 2a-1

yy的取值范围比较小:[2,Sum][2,Sum]

这样,枚举yy根据上面求和公式求xx,在分别求出a,ba,b

这个方法很好

但是发现,最后还要自己重新排序

import java.util.ArrayList;
import java.util.*;
public class Solution {
public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {
ArrayList<ArrayList<Integer> > result = new ArrayList<ArrayList<Integer> >();
ArrayList<Integer> list = new ArrayList<Integer>();
int a,b;
for(int y=2;y<=sum;y++){
if( 2*sum%y == 0){
int x = (2*sum)/y;

if( (x-y+1) %2==0){
a = (x-y+1)/2;
}else
continue;

if( a>0 && (x+y -1) %2 ==0){
b = (x + y -1)/2;
}else
continue;

add(list,a,b);
result.add(new ArrayList<Integer>(list));
list.clear();
}
}
Collections.sort(result,new innerComparator());
return result;
}
class innerComparator implements Comparator<ArrayList<Integer>>{
public int compare(ArrayList<Integer> a,ArrayList<Integer> b){
int i = 0;
while(i<a.size() && i<b.size()){
if(a.get(i) >b.get(i)){
return 1;
}else{
return -1;
}
}
return 1;
}
}

public void add(ArrayList<Integer> list,int i,int j){
if(i==j)
return;
for(int k=i;k<=j;k++)
list.add(k);
}
}


上面计算2*sum可能出现越界

方法二:两个指针

small,big,表示一个序列区间的边界

计算区间和

大于sum,去掉最小值,增加sum

等于sum,保存结果,增加big

小于sum,增加big

初始条件:

small= 1

big = 2

停止条件

small = sum/2+1

import java.util.ArrayList;
import java.util.*;
public class Solution {
public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {
ArrayList<ArrayList<Integer> > result = new ArrayList<ArrayList<Integer> >();
ArrayList<Integer> list = new ArrayList<Integer>();
int small = 1;
int big = 2;
int middle = (1 + sum)/2;
int cursum = small + big;
while(small < middle){
if(cursum == sum){
add(list,small,big);
result.add(new ArrayList<Integer>(list));
list.clear();
}
while(cursum > sum && small < middle){
cursum -= small;
small++;
if(cursum == sum){
add(list,small,big);
result.add(new ArrayList<Integer>(list));
list.clear();
}
}
big++;
cursum +=big;
}

return result;
}

public void add(ArrayList<Integer> list,int i,int j){
if(i==j)
return;
for(int k=i;k<=j;k++)
list.add(k);
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: