LeetCode Top 100 Liked Questions 15.3Sum (Java版; Medium)
题目描述
Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0?
Find all unique triplets in the array which gives the sum of zero.
Note:
The solution set must not contain duplicate triplets.
Example:
Given array nums = [-1, 0, 1, 2, -1, -4],
A solution set is:
[
[-1, 0, 1],
[-1, -1, 2]
]
绊脚案例
加入了重复组合
输入:
[-2,0,0,2,2]
输出
[[-2,0,2],[-2,0,2]]
预期结果
[[-2,0,2]]
class Solution {
public List< List< Integer> > threeSum ( int [ ] nums) {
int n = nums. length;
List< List< Integer> > list = new ArrayList < > ( ) ;
Arrays. sort ( nums) ;
int cur, L, R;
for ( int i= 0 ; i< n; i++ ) {
if ( i- 1 >= 0 && nums[ i] == nums[ i- 1 ] ) {
continue ;
}
cur = nums[ i] ;
L = i+ 1 ;
R = n- 1 ;
int target = - cur;
while ( L< R) {
int sum = nums[ L] + nums[ R] ;
if ( sum == target) {
List< Integer> al = new ArrayList < > ( ) ;
al. add ( cur) ;
al. add ( nums[ L] ) ;
al. add ( nums[ R] ) ;
list. add ( al) ;
L++ ;
R-- ;
while ( L< R && nums[ L] == nums[ L- 1 ] ) {
L++ ;
}
while ( R> L && nums[ R] == nums[ R+ 1 ] ) {
R-- ;
}
} else if ( sum > target) {
R-- ;
} else {
L++ ;
}
}
}
return list;
}
}
第一次做; 先对数组排序; 每次选定一个值, 再用双指针选取另外两个值; 双指针在有序数组中往往比较容易确定移动方向; 本题中有两个地方需要跳过处理过的元素:参照值处理过 或者 另外两个值出现过,见绊脚案例; 注意检查数组索引是否越界
双指针与有序数组 参照值大于0的话就break, 因为参照值是最小的, 不可能再有三个数相加和为0的情况了 出现过
import java. util. List;
import java. util. ArrayList;
import java. util. Arrays;
class Solution {
public List< List< Integer> > threeSum ( int [ ] nums) {
List< List< Integer> > res = new ArrayList < > ( ) ;
if ( nums== null || nums. length< 3 )
return res;
Arrays. sort ( nums) ;
int left, right, curr;
for ( int i= 0 ; i< nums. length- 2 ; i++ ) {
left = i+ 1 ;
right = nums. length - 1 ;
if ( nums[ i] > 0 )
break ;
if ( i> 0 && nums[ i] == nums[ i- 1 ] )
continue ;
while ( left< right) {
curr = nums[ i] + nums[ left] + nums[ right] ;
if ( curr> 0 )
right-- ;
else if ( curr< 0 )
left++ ;
else if ( left >= i+ 2 && nums[ left] == nums[ left- 1 ] && nums[ right] == nums[ right+ 1 ] ) {
left++ ;
right-- ;
continue ;
}
else
{
res. add ( new ArrayList < Integer> ( ) ) ;
res. get ( res. size ( ) - 1 ) . add ( nums[ i] ) ;
res. get ( res. size ( ) - 1 ) . add ( nums[ left] ) ;
res. get ( res. size ( ) - 1 ) . add ( nums[ right] ) ;
left++ ;
right-- ;
}
}
}
return res;
}
}
优秀答案; res添加元素时使用了Arrays.asList(); 重复元素的处理都用的while
class Solution {
public List< List< Integer> > threeSum ( int [ ] nums) {
Arrays. sort ( nums) ;
List< List< Integer> > res = new ArrayList < > ( ) ;
for ( int k = 0 ; k < nums. length - 2 ; k++ ) {
if ( nums[ k] > 0 ) break ;
if ( k > 0 && nums[ k] == nums[ k - 1 ] ) continue ;
int i = k + 1 , j = nums. length - 1 ;
while ( i < j) {
int sum = nums[ k] + nums[ i] + nums[ j] ;
if ( sum < 0 ) {
while ( i < j && nums[ i] == nums[ ++ i] ) ;
} else if ( sum > 0 ) {
while ( i < j && nums[ j] == nums[ -- j] ) ;
} else {
res. add ( new ArrayList < Integer> ( Arrays. asList ( nums[ k] , nums[ i] , nums[ j] ) ) ) ;
while ( i < j && nums[ i] == nums[ ++ i] ) ;
while ( i < j && nums[ j] == nums[ -- j] ) ;
}
}
}
return res;
}
}