nSum通用模板
注意:
- 输入数组必须使用 Arrays.sort排序!
- 返回List结果不包含重复值;
- 核心思路是以2Sum为基准,通过递归重复计算。其中 2Sum 主要使用双指针(两端指针/左右指针)
代码:
/**
* @param nums: 排序后的数组
* @param target: 目标值
* @param n: n数之和的n
* @param startIndex: 开始索引
* @return List<List<Integer>>
*/
public List<List<Integer>> nSum(int[] nums, int target, int n, int startIndex) {
// 返回结果
List<List<Integer>> res = new ArrayList<List<Integer>>();
// base case
if (startIndex > nums.length - 1) {
return res;
}
if (n == 2) {
int left = startIndex, right = nums.length - 1;
while (left < right) {
int twoSumTarget = nums[left] + nums[right];
// 用于消重的基准值,使用基准值的方法消重可以避免索引越界的情况
int baseLeft = nums[left], baseRight = nums[right];
if (twoSumTarget == target) {
List<Integer> tmp = new ArrayList<>();
tmp.add(nums[left]);
tmp.add(nums[right]);
res.add(tmp);
while (left < right && nums[left] == baseLeft) left++; // 消重
while (left < right && nums[right] == baseRight) right--; // 消重
} else if (twoSumTarget > target) {
right--;
} else if (twoSumTarget < target) {
left++;
}
}
} else {
// n>2的时候调用递归
for (int i = startIndex; i < nums.length; i++) {
// 注意:这里传入的下一位是i的后一位!肯定不能包括i
List<List<Integer>> nRes = nSum(nums, target - nums[i], n - 1, i + 1);
for (List<Integer> list : nRes) {
list.add(nums[i]);
res.add(list);
}
while (i < nums.length - 1 && nums[i] == nums[i + 1]) i++; // 消重
}
}
return res;
}