2つの数の合計が特定の値になる場合
配列がソートされている場合、双指針法を用いて効率的に解決できます。左端と右端から開始し、合計値を比較してポインタを移動します。
public class SumSolution {
public static int[] findTwoSum(int[] arr, int target) {
int start = 0;
int end = arr.length - 1;
while (start < end) {
int currentSum = arr[start] + arr[end];
if (currentSum == target) {
return new int[]{arr[start], arr[end]};
} else if (currentSum > target) {
end--;
} else {
start++;
}
}
return new int[]{-1, -1}; // 見つからない場合
}
}
3つの数の合計がゼロになる場合
同様に、配列をまずソートし、固定された一つの要素に対して残りの二つを双指針で探索します。重複を防ぐために、既に見つけた要素と同じものはスキップします。
import java.util.*;
public class ThreeSumSolution {
public static List findThreeSum(int[] nums) {
Arrays.sort(nums);
List result = new ArrayList<>();
for (int i = 0; i < nums.length - 2; i++) {
if (i > 0 && nums[i] == nums[i - 1]) continue;
int goal = -nums[i];
int left = i + 1, right = nums.length - 1;
while (left < right) {
int sum = nums[left] + nums[right];
if (sum == goal) {
result.add(Arrays.asList(nums[i], nums[left], nums[right]));
while (left < right && nums[left] == nums[left + 1]) left++;
while (left < right && nums[right] == nums[right - 1]) right--;
left++;
right--;
} else if (sum < goal) {
left++;
} else {
right--;
}
}
}
return result;
}
}
4つの数の合計が特定の値になる場合
この場合も、最初の二つの数を固定し、残りの二つについて双指針法を適用します。これにより、時間計算量を大幅に削減できます。
import java.util.*;
public class FourSumSolution {
public static List findFourSum(int[] nums, int target) {
Arrays.sort(nums);
List results = new ArrayList<>();
for (int i = 0; i < nums.length - 3; i++) {
if (i > 0 && nums[i] == nums[i - 1]) continue;
for (int j = i + 1; j < nums.length - 2; j++) {
if (j > i + 1 && nums[j] == nums[j - 1]) continue;
int remainingTarget = target - nums[i] - nums[j];
int left = j + 1, right = nums.length - 1;
while (left < right) {
int sum = nums[left] + nums[right];
if (sum == remainingTarget) {
results.add(Arrays.asList(nums[i], nums[j], nums[left], nums[right]));
while (left < right && nums[left] == nums[left + 1]) left++;
while (left < right && nums[right] == nums[right - 1]) right--;
left++;
right--;
} else if (sum < remainingTarget) {
left++;
} else {
right--;
}
}
}
}
return results;
}
}