1. 程式人生 > >在一個數組中查詢任意個數和為m的的組合

在一個數組中查詢任意個數和為m的的組合

最近比較鬱悶,遇到幾次類似的題目了,現在打算總結一下,防止以後又忘了

1、輸入一個遞增排序的陣列和一個數字S,在陣列中查詢兩個數,使得他們的和正好是S,如果有多對數字的和等於S,輸出兩個數的乘積最小的。

import java.util.ArrayList;
public class Solution {
     public ArrayList<Integer> FindNumbersWithSum(int[] array, int sum) {
        ArrayList<Integer> list = new ArrayList<>();
        if (array.length == 0) {
            return list;
        }
        int left = 0;
        int right = array.length-1;
        while (left < right) {
            if (array[left]+array[right]==sum){
                list.add(array[left]);
                list.add(array[right]);
                return list;
            }
            if (array[left]+array[right]>sum){
                right--;
            }
            if (array[right]+array[left]<sum){
                left++;
            }
        }
        return list;
    }
}
直接計算即可,比較簡單

2、劍指offer上一題目 小明很喜歡數學,有一天他在做數學作業時,要求計算出9~16的和,他馬上就寫出了正確答案是100。但是他並不滿足於此,他在想究竟有多少種連續的正數序列的和為100(至少包括兩個數)。沒多久,他就得到另一組連續正數和為100的序列:18,19,20,21,22。現在把問題交給你,你能不能也很快的找出所有和為S的連續正數序列? Good Luck!

import java.util.ArrayList;
public class Solution {
   public ArrayList<ArrayList<Integer>> FindContinuousSequence(int sum) {
        ArrayList<ArrayList<Integer>> listAll = new ArrayList<>();
        for (int i = (int) Math.sqrt(sum * 2); i >= 2; i--) {
            if (((i & 1) == 1 && sum % i == 0) || (sum % i) * 2 == i) {
                ArrayList<Integer> list = new ArrayList<>();
                for (int j = 0, k = (sum / i) - (i-1)/ 2; j< i; j++, k++) {
                    list.add(k);
                }
                listAll.add(list);
            }
        }
        return listAll;
    }
}

3、最近遇到比較多的,輸入兩個數n,m,要求輸出1-n中所有和為m的組合

思路比較簡單1-n個每個元素無非就是兩種情況,加入或者不加入 因此我直接採用遞迴獲取所有的組合,1表示加入這個元素,0 表示不加入這個元素,最終求出所有的情況

package com.sharetime.test;


import java.util.*;

/**
 * @Author: yd
 * @Date: 2018/10/9 20:02
 * @Version 1.0
 */
public class Main {
    public static void main(String[] args) {
        new Main().getInfo();
    }

    public void getInfo() {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        getlist(m);
        for (List<Integer> sh : listAll) {
            int add = 0;
            List<Integer> lk = new ArrayList<>();
            for (int i = 0; i < sh.size(); i++) {
                if (sh.get(i) == 1) {
                    add += i + 1;
                    lk.add(i + 1);
                }
            }
            if (add == m)
                res.add(new ArrayList<>(lk));
        }
        System.out.println(res);
    }

    List<Integer> list = new ArrayList<>();
    List<List<Integer>> listAll = new ArrayList<>();
    List<List<Integer>> res = new ArrayList<>();

    /**
     * 獲取所有組合情況
     *
     * @param target
     */
    void getlist(int target) {
        if (target == 0) {
            listAll.add(new ArrayList<>(list));
            return;
        }
        list.add(0);
        getlist(target - 1);
        list.remove(list.size() - 1);
        list.add(1);
        getlist(target - 1);
        list.remove(list.size() - 1);
    }
}

這樣做時間複雜度確實有點大,可以進行一定優化,比如講遞迴改成迴圈 還有 100110001如果這個組合和為m了那麼就沒必要再判斷 100111111了,因為肯定大於m,(當然這是在數都為正數的情況下)