15.三数之和
1、暴力枚举+链表元素去重
不出意外直接超时

class Solution {
public List<List<Integer>> threeSum(int[] nums) {
int size = nums.length;
//枚举所有结果
Arrays.sort(nums);
List<List<Integer>> res = new LinkedList<>();
for(int i = 0; i < size; i++){
for(int j = i + 1; j < size; j++){
for(int k = j + 1; k < size; k++){
if(nums[i] + nums[j] + nums[k] == 0){
ArrayList<Integer> l = new ArrayList(Arrays.asList(nums[i],nums[j], nums[k]));
res.add(l);
}
}
}
}
//排序去重
Collections.sort(res, (o1, o2) -> {
if(o1.get(0).equals(o2.get(0))){
if(o1.get(1).equals(o2.get(1))){
if(o1.get(2).equals(o2.get(2))){
return 0;
}
return o1.get(2)-o2.get(2);
}
return o1.get(1)-o2.get(1);
}
return o1.get(0) - o2.get(0);
});
List<Integer> pre = null;
for(int i = 0; i < res.size();){
if( pre != null && pre.get(0).equals(res.get(i).get(0)) && pre.get(1).equals(res.get(i).get(1)) && pre.get(2).equals(res.get(i).get(2))){
res.remove(i);
}else{
pre = res.get(i);
i++;
}
}
return res;
}
}
可恶还是无法AC么。。

2.在暴力枚举的基础上考虑两个数的和利用HashMap优化复杂度

class Solution {
public List<List<Integer>> threeSum(int[] nums) {
int size = nums.length;
Arrays.sort(nums);
HashMap<Integer, Integer> map = new HashMap<>();
for(int i = 0; i < size; i++){
map.put(nums[i],i);
}
//枚举所有结果
List<List<Integer>> res = new LinkedList<>();
for(int i = 0; i < size; i++){
for(int j = i + 1; j < size; j++){
Integer k = map.get(0 - nums[i] - nums[j]);
if(k!=null&& k > j){
ArrayList<Integer> l = new ArrayList(Arrays.asList(nums[i],nums[j], nums[k]));
res.add(l);
}
}
}
//排序去重
Collections.sort(res, (o1, o2) -> {
if(o1.get(0).equals(o2.get(0))){
if(o1.get(1).equals(o2.get(1))){
if(o1.get(2).equals(o2.get(2))){
return 0;
}
return o1.get(2)-o2.get(2);
}
return o1.get(1)-o2.get(1);
}
return o1.get(0) - o2.get(0);
});
List<Integer> pre = null;
for(int i = 0; i < res.size();){
if( pre != null && pre.get(0).equals(res.get(i).get(0)) && pre.get(1).equals(res.get(i).get(1)) && pre.get(2).equals(res.get(i).get(2))){
res.remove(i);
}else{
pre = res.get(i);
i++;
}
}
return res;
}
}
优化之后就多跑了一个样例,哈基和你这家伙。。

3. 在两个数之和中不能对数组排序是因为要求返回数组下标,一经排序下标就乱了,但是本题目不需要返回下标,所以可以排序利用双指针降低复杂度
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
int size = nums.length;
Arrays.sort(nums);
List<List<Integer>> res = new LinkedList<>();
int a = 1, b = 1, c = 1;
int h, t;
for (int i = 0; i < size; i++) {
h = i + 1;
t = size - 1;
//寻找和为0-nums[i]的两个数
while (h < t) {
if (nums[h] + nums[t] < 0 - nums[i]) {
h++;
} else if (nums[h] + nums[t] > 0 - nums[i]) {
t--;
} else {
List<Integer> list = new ArrayList<>(Arrays.asList(nums[i], nums[h], nums[t]));
res.add(list);
int old_h = nums[h];
while(h < t && old_h == nums[++h]);
int old_t = nums[t];
while(h < t && old_t == nums[--t]);
}
}
}
//排序去重
Collections.sort(res, (o1, o2) -> {
if(o1.get(0).equals(o2.get(0))){
if(o1.get(1).equals(o2.get(1))){
if(o1.get(2).equals(o2.get(2))){
return 0;
}
return o1.get(2)-o2.get(2);
}
return o1.get(1)-o2.get(1);
}
return o1.get(0) - o2.get(0);
});
List<Integer> pre = null;
for(int i = 0; i < res.size();){
if( pre != null &&
pre.get(0).equals(res.get(i).get(0)) &&
pre.get(1).equals(res.get(i).get(1)) &&
pre.get(2).equals(res.get(i).get(2))){
res.remove(i);
}else{
pre = res.get(i);
i++;
}
}
return res;
}
}
终于。。超过百分之五也是神人了

一直以为HashSet去重比较的是地址就没敢用,我太蠢了
用HashSet复杂度比自己的去重低一点
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
int size = nums.length;
Arrays.sort(nums);
HashSet<List<Integer>> set = new HashSet<>();
int a = 1, b = 1, c = 1;
int h, t;
for (int i = 0; i < size; i++) {
h = i + 1;
t = size - 1;
//寻找和为0-nums[i]的两个数
while (h < t) {
if (nums[h] + nums[t] < 0 - nums[i]) {
h++;
} else if (nums[h] + nums[t] > 0 - nums[i]) {
t--;
} else {
List<Integer> list = new ArrayList<>(Arrays.asList(nums[i], nums[h], nums[t]));
Collections.sort(list);
set.add(list);
int old_h = nums[h];
while(h < t && old_h == nums[++h]);
int old_t = nums[t];
while(h < t && old_t == nums[--t]);
}
}
}
List<List<Integer>> res = new LinkedList<>(set);
return res;
}
}

浙公网安备 33010602011771号