15. 3Sum
1、原题
Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
2、解读与思路
这道题目的意思不是很难理解,就是要求我们找到一个数组中所有3个数之后为0的不同组合。
思路:一开始看到这道题并没有什么好的想法;就只好采用最笨的方法了,则就是遍历三遍数组。当然简单的遍历三遍肯定是要超时的。所以我们要对其进行相应的优化。
1、首先对数组进行快排,获得一个从小到大的有序数组。
2、开始遍历数组,优化将三层变为两层,第一层数组i从0到length-1;第二层j,k两个小标,j从i+1开始,k则从length-1开始;当j与k相遇时则结束第二层的遍历或三个数相加为0时也结束当前第二层遍历.
3、细节注意,由于是要找到不同的组合,所有我们在遍历时要进行相应的判断才行。
3、实现代码
public class Solution {
//快排
public void quickSort(int[] nums, int low, int high) {
int l = low;
int h = high;
int item = nums[l];
while (l < h) {
while (l < h && nums[h] >= item) {
h--;
}
if (l < h) {
int temp = nums[l];
nums[l] = nums[h];
nums[h] = temp;
}
while (l < h && nums[l] <= item) {
l++;
}
if (l < h) {
int temp = nums[l];
nums[l] = nums[h];
nums[h] = temp;
}
}
if (l > low) {
quickSort(nums, low, l - 1);
}
if (h < high) {
quickSort(nums, l + 1, high);
}
}
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> finals = new ArrayList<List<Integer>>();
if (nums.length == 0) {
return finals;
}
//排序
quickSort(nums, 0, nums.length - 1);
for (int i = 0; i < nums.length; i++) {
//由于从小到大排序,nums[i]大于0时肯定结束了
if (nums[i] > 0) {
break;
}
//排除nums[i]相同的情况
if (i > 0 && nums[i] == nums[i-1]) {
continue;
}
//定义第二层两个下标
int j = i + 1;
int k = nums.length - 1;
int target = -nums[i];
while (j < k) {
if (nums[j] + nums[k] == target) {
finals.add(Arrays.asList(nums[i], nums[j], nums[k]));
j++;
k--;
//排除nums[j]与nums[i]相同的情况
while (j < k && nums[j] == nums[j - 1]) {
j++;
}
while (j < k && nums[k] == nums[k + 1]) {
k--;
}
} else if (nums[j] + nums[k] > target) {
//大于0说明nums[k]过大,将其减小
k--;
} else {
//小于0说明目前nums[j]过小,将其增大
j++;
}
}
}
return finals;
}
}
4、总结与思考
在看提交记录时,发现有两个不同的集中区域;不幸的是我在靠后的集中区域;这就表明还有一种较优的方法我还没有想到。待我静静思考再来看一看。