演算法題(二十七):和為S的連續正數序列
阿新 • • 發佈:2018-12-20
題目描述
小明很喜歡數學,有一天他在做數學作業時,要求計算出9~16的和,他馬上就寫出了正確答案是100。但是他並不滿足於此,他在想究竟有多少種連續的正數序列的和為100(至少包括兩個數)。沒多久,他就得到另一組連續正數和為100的序列:18,19,20,21,22。現在把問題交給你,你能不能也很快的找出所有和為S的連續正數序列?
分析
有兩種方法可解此題
1.雙指標法
規定一個視窗,視窗左右兩邊是兩個指標,根據視窗內值的和來確定視窗的位置和長度。若當前視窗內和小於S,右指標右移一位,若大於S則左指標右移一位,若等於S則將視窗內的值儲存到一個list中,並將左指標右移一位,重新開始,走到左指標超過右指標。
2.當n為奇數時,序列的中數正好是序列的均值即,則。當n為偶數時均值為中間兩個數的均值,這個平均值的小數部分為0.5,則。由等差求和可知。所以遍歷2~之間n的值。中間值為,起始值為。
程式碼
import java.util.ArrayList; public class ContinualSum { public static void main(String[] args) { // TODO Auto-generated method stub ArrayList<ArrayList<Integer>> res = fun2(50); for(ArrayList<Integer> list: res){ for(int num: list){ System.out.print(num+","); } System.out.println(); } } public static ArrayList<ArrayList<Integer>> fun1(int sum){ ArrayList<ArrayList<Integer>> res = new ArrayList<>(); int plow=1; int phigh=2; while(plow<phigh){ int cur = (phigh+plow)*(phigh-plow+1)/2; if(cur == sum){ ArrayList<Integer> list = new ArrayList<>(); for(int i=plow; i<=phigh; i++){ list.add(i); } res.add(list); plow++; }else if(cur<sum){ phigh++; }else{ plow++; } } return res; } public static ArrayList<ArrayList<Integer>> fun2(int sum){ ArrayList<ArrayList<Integer>> res = new ArrayList<>(); int n=(int) Math.sqrt(2*sum); for(; n>=2; n--){ if((n & 1)==1 && sum % n==0 || (sum%n)*2==n){ ArrayList<Integer> list = new ArrayList<>(); //j是開始值 for(int i=0, j=(sum/n)-(n-1)/2; i<n; i++, j++){ list.add(j); } res.add(list); } } return res; } }