1.题目解析
这道题的简单版:2sum
题目的要求有三:
- 确定一个数c,并找到另外两个数a,b,使得a+b=-c
- 确定的三元组不能有重复,即我们需要对数据中重复的数据进行处理
- 能否选择同一个数(即对应的下标的两个数或三个数)确定一个等式(这个是我自己提出的疑问不知道是不是我没理清题目的意思,解法中默认这种情况是不成立的)
2.实现代码
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> lists = new LinkedList<>();
if(nums.length >= 3) {
Arrays.sort(nums);
for (int mark = 0; mark < nums.length - 2; mark ++) {
if (nums[mark] > 0) break;
if (mark > 0 && nums[mark] == nums[mark - 1]) continue;
for (int i = mark + 1, j = nums.length - 1; i < j; ) {
int sum = nums[mark] + nums[j] + nums[i];
if (sum == 0) {
lists.add(Arrays.asList(nums[mark],nums[i],nums[j]));
while(i < j && nums[i + 1] == nums[i]) i++;
while(i < j && nums[j - 1] == nums[j]) j--;
i++;
j--;
} else if (sum > 0)
j--;
else
i++;
}
}
}
return lists;
}
对数据进行排序的原因:因为题目要求不允许结果数组有重复,那么就需要我们在代码中对有可能出现的重复情况进行处理,重复性的检验方法有很多,但大部分都要新建一个数据结构对数据进行归纳,因此我选择对数组进行排序来优化重复性检验的过程。调用JAVA提供的库函数Arrays.sort()
就可以排序了。
接下来就是算法的核心思路:
- 首先固定一个数c(这里使用遍历的方法,扫描数组)
- 确定两个指针a,b。a从c+1开始,b从nums.length-1开始向中间扫描。(这里a不从0开始扫描的原因是确定c时就已经把前面的情况考虑到了)
- 确定范围的方法:
- a+b+c>0,说明a+b的结果大了,那么较大数需要减小,即b向左移
- a+b+c<0,说明a+b的结果小了,那么较小数需要增大,即a向右移
- a+b+c=0,说明是正确的结果,调用
Arrays.asList()
产生新链表合并到结果中,然后让a,b继续向中间移动,因为还有可能会有别的情况。 - 在a,b移动的过程中还应该对出现重复的数字筛除