题目描述
主要是解决重复 的问题:如何去除重复解、在有大量重复解的情况下如何让算法跑得更快
代码 & 解题思路
先排序 ,按照大小顺序来做。 思路 :固定第一个数,用双指针分别代表另外两个指针去除重复值:对三个数,分别进行去除重复解 的行为(见代码注释): 第一个数:如果num[i] == num[i-1],那么num[i-1]肯定已经把num[i]的任务给完成了 ,那么继续进行对num[i]作为第一个数的求解并没有意义,而且可能会带来重复解,因此跳过 第二个数:比如说left将要渡过“222”,那么用第一个2作为解时,剩下的两个2就已经没有意义了,于是可以直接跳过后两个2。 第三个数:和第二个数的原理一样。 注意:要先取得解,再进行跳过重复 ,直接跳重复,再取值会出问题,或需要更多判断。
class Solution { public List < List < Integer > > threeSum ( int [ ] nums) { List < List < Integer > > ans = new ArrayList < List < Integer > > ( ) ; int len = nums. length; if ( len < 3 ) { return ans; } Arrays . sort ( nums) ; if ( nums[ 0 ] > 0 || nums[ len - 1 ] < 0 ) { return ans; } int groupIndex = 0 ; for ( int i = 0 ; i < len - 2 ; i++ ) { if ( i > 0 && nums[ i] == nums[ i - 1 ] ) { continue ; } int left = i + 1 , right = len - 1 ; while ( left < right) { int temp = nums[ i] + nums[ left] + nums[ right] ; if ( temp == 0 ) { ans. add ( new ArrayList < Integer > ( ) ) ; ans. get ( groupIndex) . add ( nums[ i] ) ; ans. get ( groupIndex) . add ( nums[ left] ) ; ans. get ( groupIndex) . add ( nums[ right] ) ; groupIndex++ ; while ( left < right && nums[ left+ 1 ] == nums[ left] ) ++ left; while ( right < right && nums[ right- 1 ] == nums[ right] ) -- right; left++ ; right-- ; } else if ( temp > 0 ) { right-- ; } else { left++ ; } } } return ans; }
}
时间复杂度:排序O(nlogn) + 遍历固定第一解O(n) * 双指针遍历 O(n),算是O(n2n^2 n 2 ) 空间复杂度:O(1)
二刷更新
之前的代码看看注释就好,写的有点冗余了,不到20行就能解决的事
class Solution { public List < List < Integer > > threeSum ( int [ ] nums) { List < List < Integer > > ans = new ArrayList < > ( ) ; Arrays . sort ( nums) ; for ( int i = 0 ; i < nums. length - 2 ; i++ ) { if ( i > 0 && nums[ i] == nums[ i - 1 ] ) continue ; int left = i + 1 , right = nums. length - 1 ; while ( left < right) { int temp = nums[ i] + nums[ left] + nums[ right] ; if ( temp == 0 ) { List < Integer > element = new ArrayList < > ( ) ; element. add ( nums[ i] ) ; element. add ( nums[ left] ) ; element. add ( nums[ right] ) ; ans. add ( element) ; while ( left < right && nums[ left + 1 ] == nums[ left] ) left++ ; while ( left < right && nums[ right - 1 ] == nums[ right] ) right-- ; left++ ; right-- ; } else if ( temp > 0 ) right-- ; else left++ ; } } return ans; }
}