四數之和
給一個包含n個數的整數數組S,在S中找到所有使得和爲給定整數target的四元組(a, b, c, d)。
注意事項
四元組(a, b, c, d)中,需要滿足a <= b <= c <= d
答案中不可以包含重複的四元組。
例如,對於給定的整數數組S=[1, 0, -1, 0, -2, 2] 和 target=0. 滿足要求的四元組集合爲:
(-1, 0, 0, 1)
(-2, -1, 1, 2)
(-2, 0, 0, 2)
這是一道數組求和的問題,看了網上很多解答的算法,比較流行的是一個先排序,然後選兩個數字,接着後面用兩個指針分別指向剩下數組開始和結束,逐步移向中間求和看和targer是否相等,但是這樣的算法感覺實現起來太不優雅了。想到一個深度遍歷的算法,可以到達同樣的效果,而且以後無論多少個數求和,都能解決。代碼如下:
public ArrayList<ArrayList<Integer>> fourSum(int[] numbers, int target) {
Arrays.sort(numbers);
ArrayList<ArrayList<Integer>> ret = new ArrayList<>();
dfs(ret, new ArrayList<Integer>(), numbers, 0, target);
return ret;
}
private void dfs(ArrayList<ArrayList<Integer>> ret, ArrayList<Integer> condidate, int[] numbers, int curIndex,
int target) {
// 以後求n數和,只要改這裏就能解決,比如4改爲3,改爲5
if (condidate.size() == 4) {
int total = getSum(condidate);
if (total == target) {
ret.add(new ArrayList<>(condidate));
}
return;
}
if (curIndex > numbers.length - 1) {
return;
}
for (int i = curIndex; i < numbers.length; i++) {
// 如果是一樣的數字,直接忽略,否則會有重複的答案
if (i != curIndex && numbers[i] == numbers[i - 1]) {
continue;
}
condidate.add(numbers[i]);
// 如果已經大於target,並且當前數字大於0,再循環加下去已經沒有意義了,因爲只會更大,直接return
if (getSum(condidate) > target && numbers[i] > 0) {
if (!condidate.isEmpty()) {
condidate.remove(condidate.size() - 1);
}
return;
}
dfs(ret, condidate, numbers, i + 1, target);
if (!condidate.isEmpty()) {
condidate.remove(condidate.size() - 1);
}
}
}
private int getSum(ArrayList<Integer> condidate) {
int total = 0;
for (Integer num : condidate) {
total += num;
}
return total;
}