和为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); } }
相关文章推荐
- hibernate常用API详解
- twsited(4)--不同模块用redis共享以及用web发送数据到tcpserver
- 一些IT技术网站收藏
- Ecshop一些文档
- BLOCK
- Python的多线程/多进程
- JavaScript笔记整理——驯服线程和定时器
- ZooKeeper架构学习(一)
- Android 性能指标检测工具
- 关于触发点(trigger point )
- xCode 使用快捷键a
- 学习DVB知识的疑问与自我解答
- Android从res/values/strings.xml获取字符串文件路径:res/values/strings.xml <resources> <string name="main_ve
- IntelliJ Idea 常用快捷键列表
- <性能测试进阶指南>性能测试招聘要求
- ecshop_debug_mode
- ecshop验证码位运算
- a ecshop captcha bug
- 安装php环境
- oracle开启numa的支持