和爲S的連續正數序列

題目描述:

現在要求有多少種連續的正數序列的和爲100(至少包括兩個數)。其中一組連續正數和爲100的序列:18,19,20,21,22。現在把問題交給你,你能不能也很快的找出所有和爲S的連續正數序列? 

思路:

由於題目要求至少包含兩個數,那麼所有可能的序列的最大值均不會超過(sum + 1) >> 1;
1, 2, start-1, start, start+1, start+2, ..., end-1 , end.
於是,從 end= (sum + 1)>> 1, start = end - 1 開始求和。
while( start > 0){
    tmp += start;
    if(tmp == sum)
        將 start, ..., end記錄下來;
        tmp -= end;
        end--;
        start--;
    else if(tmp < sum)
        start--;
    else //tmp > sum
        tmp -= end;
        end--;
        start--;
    //每比較一次,需要更新start,end,tmp的值
}

時間複雜度爲O(start) = O(sum)

代碼實現如下:

import java.util.ArrayList;

public class SequenceSum {

    public static void main(String[] args) {
        int target = 9;
        for (ArrayList<Integer> list : findSequence(target)) {
            for (int x : list)
                System.out.print(x + " ");
            System.out.println("");
        }
    }

    private static ArrayList<ArrayList<Integer>> findSequence(int sum) {
        if (sum <= 2)
            return new ArrayList<>();
        int end = (sum + 1) >> 1, start = end - 1, tmp = end;
        ArrayList<ArrayList<Integer>> aal = new ArrayList<>();
        while (start > 0) {
            tmp += start;
            if (tmp == sum) {
                ArrayList<Integer> al = new ArrayList<>();
                for (int i = start; i <= end; i++) {
                    al.add(i);
                }
                aal.add(al);
                tmp -= end;
                end--;
            } else if (tmp > sum) {
                tmp -= end;
                end--;
            }
            start--;

    }
}

輸出如下:

4 5 
2 3 4 

也可以根據序列start從小到大輸出序列
aal.add(0,al);
但是由於ArrayList是基於數組實現的,每次調用add(0,al)必然導致0以後的所有值需要後移一位,效率低下。可以將ArrayList換成LinkedList,這樣效率會高一些,特別是鏈表較長時,效率會更高。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章