求数组中三数之和为零的所有不重复解。
解题思想:
1. 数组非null且数组的长度大于等于3
2. 对数组进行排序后进行第三步的处理 {下面的代码中使用的是快排进行数组的排序,时间复杂度O(NlogN)}
3. 遍历有序数组:
- 若nums[i]大于0,则后面的有序序列中不可能存在三数之和为零的结果。直接返回当前结果即可
- 对与nums[i]重复的元素进行跳过,避免出现重复解
- 在i+1和length-1之间寻找满足条件的解。left=i+1,right=length-1,当left<right时则进行循环处理
- 若nums[i]+nums[left]+nums[right]等于0,则找到一个解,此时将left与right分别移动找到下一个与自己不相等的数字位置
- 若大于0,则说明right需要减小,此时也可以将与当前元素相等的过滤掉,避免无用的操作
- 若小于0,则说明left需要增大,此时也可以将与当前元素相等的过滤掉,避免无用的操作
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> result = new ArrayList<>();
if (nums == null || nums.length < 3) {
return result;
}
quickSort(nums, 0, nums.length - 1);
for (int i = 0; i < nums.length; i++) {
if (nums[i] > 0) {
return result;
}
int left = i + 1, right = nums.length - 1;
while (left < right) {
if (nums[left] + nums[right] == 0 - nums[i]) {
List<Integer> list = new ArrayList<Integer>();
list.add(nums[i]);
list.add(nums[left]);
list.add(nums[right]);
result.add(list);
while (left < right && nums[right] == nums[right - 1]) {
right--;
}
right--;
while (left < right && nums[left] == nums[left + 1]) {
left++;
}
left++;
} else if (nums[left] + nums[right] > 0 - nums[i]){
while (left < right && nums[right] == nums[right - 1]) {
right--;
}
right--;
} else {
while (left < right && nums[left] == nums[left + 1]) {
left++;
}
left++;
}
}
while (i < nums.length - 1 && nums[i] == nums[i + 1]) {
i++;
}
}
return result;
}
void quickSort(int[] array, int left, int right) {
if (left >= right) {
return;
}
int mid = partition(array, left, right);
quickSort(array, left, mid - 1);
quickSort(array, mid + 1, right);
}
int partition(int[] array, int left, int right) {
int tmp = array[left];
while (left < right) {
while (array[right] >= tmp && left < right) {
right--;
}
if (left < right) {
array[left++] = array[right];
}
while (array[left] <= tmp && left < right) {
left++;
}
if (left < right) {
array[right--] = array[left];
}
}
array[left] = tmp;
return left;
}
}