015J. Three Sum
https://leetcode.com/problems/3sum/
Method: O(N^2)
Two Sum 因为可以达到比 O(NlogN)更好的O(N),所以不用Sort.
Three Sum 应当先Sort 比较合算. 剩下的比较平庸。
这里用到了167 题的代码。
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> ans = new ArrayList<>();
int target = 0;
for(int i = 0; i < nums.length - 2; i++){
target = 0 - nums[i];
int left = i + 1;
int right = nums.length - 1;
// 这个是为了避免重复的 i
if(i == 0 || (i> 0 && nums[i]!=nums[i-1] )){
while(left < right){
if( nums[left] + nums[right] < target){
left++;
}else if(nums[left] + nums[right] > target){
right--;
}else{
List<Integer> temp = new ArrayList<>();
temp.add(nums[i]);
temp.add(nums[left]);
temp.add(nums[right]);
ans.add(temp);
//以下两句是为了避免重复的 left 和 right
while (left < right && nums[left] == nums[left+1]) left++;
while (left < right && nums[right] == nums[right-1]) right--;
left++;
right--;
}
}
}
}
return ans;
}
}
又一次做
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
// get zero;
// need solution set.
Arrays.sort(nums);
List<List<Integer>> ans = new ArrayList<>();
for(int i = 0; i < nums.length - 2; i ++ ) {
// 减 2 是为了给 left 和 righ 留位置
int target = 0 - nums[i];
int left = i + 1;
int right = nums.length - 1;
// 这个题的问题是存在重复的数字,所以需要跳过。 但是是因为不能有 triplet 相同,而不是因为
// 有重复的数字。重复的数字是允许的。i取的是一串重复数字中的第一个。
if( i == 0 || (i > 0 && nums[i] != nums[i - 1] )) {
while(left < right) {
int sum = nums[left] + nums[right];
if(sum < target) {
left ++;
}else if(sum > target) {
right --;
}else {
Integer[] tempAns = new Integer[]{nums[i], nums[left], nums[right]};
List<Integer> temp = Arrays.asList(tempAns);
ans.add(temp );
// 以下是为了排除重复的数字。
while( (left < right) && nums[left] == nums[left + 1] ) {
left ++;
}
while( (left < right) && nums[right] == nums[right - 1] ) {
right--;
}
//因为要全部的答案,所以不能停
left++;
right--;
}
}
}
}
return ans;
}
}
最好是这样:
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> ans = new ArrayList<>();
for(int i = 0; i < nums.length - 2; i ++ ) {
// 减 2 是为了给 left 和 right 留位置
// 这个题的问题是存在重复的数字,所以需要跳过。 但是是因为不能有 triplet 相同,而不是因为
// 有重复的数字。重复的数字是允许的。i取的是一串重复数字中的第一个。
if( i > 0 && nums[i] == nums[i - 1] ){
continue;
// 注意 这里只能是 continue; 而不能是 i++ 或者 while() i++
// continue 也是起到了 i++ 的作用 但是它相当于把 for loop 的
// conditional statement 一直带上了。
// 所以 if continue 的效果是对 for loop 起到了增加一个额外的 conditional statement 的作用
}
int target = 0 - nums[i];
int left = i + 1;
int right = nums.length - 1;
while(left < right) {
int sum = nums[left] + nums[right];
if(sum < target) {
left ++;
}else if(sum > target) {
right --;
}else {
Integer[] tempAns = new Integer[]{nums[i], nums[left], nums[right]};
List<Integer> temp = Arrays.asList(tempAns);
ans.add(temp );
// 以下是为了排除重复的数字。
while( (left < right) && nums[left] == nums[left + 1] ) {
left ++;
}
while( (left < right) && nums[right] == nums[right - 1] ) {
right--;
} // 注:2022年再看发现这一行可以去掉,因为left一侧的重复数字被排除了之后,一定不会再选择重复的right了。
//因为要全部的答案,所以不能停
left++;
right--;
}
}
}
return ans;
}
}
2023 又写:
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> ans = new ArrayList<>();
for (int i = 0; i < nums.length - 2; i++) {
if (i > 0 && nums[i] == nums[i - 1]) continue;
int lo = i + 1;
int hi = nums.length - 1;
while (lo < hi) {
if (nums[lo] + nums[hi] == -nums[i]) {
List<Integer> triplet = new ArrayList<>();
triplet.add(nums[i]);
triplet.add(nums[lo]);
triplet.add(nums[hi]);
ans.add(triplet);
while (lo < hi && nums[lo] == nums[lo + 1]) lo++;
while (lo < hi && nums[hi] == nums[hi - 1]) hi--;
lo++;
hi--;
} else if (nums[lo] + nums[hi] < -nums[i]) {
lo++;
} else {
hi--;
}
}
}
return ans;
}
}
2023 09
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> ans = new ArrayList<>();
for (int i = 0; i < nums.length - 2; i++) {
if (i > 0 && nums[i] == nums[i - 1]) continue;
int target = - nums[i];
int left = i + 1;
int right = nums.length - 1;
while (left < right) {
int sum = nums[left] + nums[right];
if (sum < target) {
left++;
} else if (sum > target) {
right--;
} else {
ans.add(Arrays.asList(new Integer[]{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--;
}
}
}
return ans;
}
}
Last updated
Was this helpful?