leetcode 15.三数之和 3Sum
第一步:
判断问题类型,观察 信息之间关系,除了暴力求解,是否有稍微更好一点的解法,如果没有用最简单的方法进行暴力求解法
测试中发现有重复问题,解决重复,发现排序才可以更好的解决重复。
以此写出第一个代码
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
//考虑 特殊值,边界值,再优化
//不排序的话 去重很难
Arrays.sort(nums);
List<List<Integer>> result = new ArrayList();
for(int i = 0; i < nums.length-2; i++){
//排序以后的去重,i==0是因为 第一次的值不算重复的
if(nums[i] < 0){
if(i==0 || i>0 && nums[i]!=nums[i-1]){
//剩下两数之和
int sum = 0 - nums[i];
for(int j=i+1; j < nums.length-1; j++){
for(int k = j+1; k < nums.length; k++){
if(nums[j]+nums[k] == sum){
List<Integer> list = new ArrayList();
list.add(nums[i]);
list.add(nums[j]);
list.add(nums[k]);
result.add(list);
}
}
}
}
}
}
return result;
}
}
发现排序后,算法可以更加优化
因为三数之和 与 排序好的数字是有一定关系的。
-7 -3 -2 0 2 3 4 5 6 7
a b c
1.三数全正 全负 pass 如果从最左边开始试起,头部大于0就没有必要算下去了。
2.以第一个数为基准,从数组两边开始寻找值,如果a <0 c<0 停止,a > 0 , c>0 停止
b+c + a > 0 c--
b+c + a < 0 b++
循环得到 等于0 的值
特殊情况:
-7 = 2 5 ,3 4
出现重复值,如何跳过
最终解法
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
//考虑 特殊值,边界值,再优化
//不排序的话 去重很难
Arrays.sort(nums);
List<List<Integer>> result = new ArrayList();
for(int i = 0; i < nums.length-2; i++){ //第一层循环控制第一个基准值
//根据有序数组特性 排除一些无效数组
if(nums[i] > 0 || (nums[i] < 0 && nums[nums.length-1]<0)) return result;
//排序以后的去重,i==0是因为 第一次的值不算重复的
if(i==0 || i>0 && nums[i]!=nums[i-1]){
//剩下两数之和
int sum = 0 - nums[i];
int left = i+1,right = nums.length -1;
while(left < right){
if(nums[left]+nums[right] == sum){
result.add(Arrays.asList(nums[i],nums[left],nums[right]));
//数值相等 需要考虑下一次移动,1.是否有重复数 2.没有重复数怎么移动
//从 -4 = 2 ,2 开始 ,左右差值就至少是2了,-7 = 2 5 ,3 4为最小差值数
//所以相等后,至少两边都要挪动一位数
while(left < right && nums[left]==nums[left+1] ) left++;
while(left < right && nums[right]==nums[right-1] ) right--;
left++;
right--;
}else if(nums[left]+nums[right] < sum){
//1.考虑左边移动还是右边移动 left + right + num < 0 left++
//2.考虑重复值,知道是左起点移动后,那就是检查左边的重复值
while(left < right && nums[left]==nums[left+1])left++;
left++;
}else{ //可以省略 while(l < r && nums[left]==nums[left+1])left++;
while(left < right && nums[right]==nums[right-1])right--;
right--;
}
}
}
}
return result;
}
}
国外大牛解法
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> result = new ArrayList();
for(int i = 0; i < nums.length-2; i++){
if(i == 0 || (i > 0 && nums[i] != nums[i-1]) ){
int left = i+1,right = nums.length -1,sum = 0 - nums[i];
while(left < right){
if(nums[left]+nums[right] == sum){
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(nums[left]+nums[right] < sum)
left++;
else
right--;
}
}
}
return result;
}
}