Description
Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution.
For example, given array S = {-1 2 1 -4}, and target = 1.
The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).
Solution
- 指定i,j,k分別是目標元素,即滿足i < j < k, 且arr[i] + arr[j] + arr[k] == 0。
- 固定i的值(從0到arr.length-1),讓j從i+1開始,k從arr.length開始,通過計算三個元素之和sum = arr[i] + arr[j] + arr[k]。如果sum == 0,說明符合要求;如果sum < 0,那麼j++;否則sum > 0,那麼k–;直到j和k重合。
- 爲避免出現重複結果(例如[-1,-1,-1, 0,1,1,1]可能會出現多個[-1, 0 , 1]的結果),需要根據當前元素和上一個元素是否一樣來移動索引。
Code
public List<List<Integer>> threeSum(int[] arr) {
int i = 0, j, k = arr.length - 1;
// 從小到大排序,方便後面大小比較和移動
Arrays.sort(arr);
List<List<Integer>> result = new ArrayList<List<Integer>>();
List<Integer> list = null;
while (i < k) {
k = arr.length - 1;
j = i + 1;
while (j < k) {
// 求總和
int sum = arr[i] + arr[j] + arr[k];
if (sum == 0) {
// 對於符合要求則封裝到result中
list = new ArrayList<Integer>(3);
list.add(arr[i]);
list.add(arr[j]);
list.add(arr[k]);
result.add(list);
// 同時移動兩個索引,防止重複答案
j++;
k--;
// 消除重複結果
while (j < k && arr[j - 1] == arr[j])
j++;
while (j < k && arr[k + 1] == arr[k])
k--;
} else if (sum < 0) {
// 如總和偏小,則右移第二個元素的位置
j++;
} else {
// 如總和偏大,則左移第三個元素
k--;
}
}
// 消除重複出現的結果
while (arr[++i] == arr[i - 1] && i <= arr.length - 3);
}
return result;
}