LeetCode No15. 三数之和
题目
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例 1:
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
示例 2:
输入:nums = []
输出:[]
示例 3:
输入:nums = [0]
输出:[]
思路
首先第一反应就是暴力,三重循环,然后时间复杂度O(n^3),按照题目给的数据范围应该不会超时,然而写完之后提交直接超时。那就优化呗,看题目的样例,似乎是对返回的顺序什么的没有要求,那么就想到排序,然后对排序后的数组去取值,这样就想到如下两种方法:
二分查找
既然三重循环不行,那我减少一层循环试试,先用两层循环找到两个数a、b,因为需要三个数之和为0,那么另外一个数必然是 -(a+b),因为数组已经有序,找这个数就可以用二分,时间复杂度为O(n^2*log(n))。
双指针
既然已经能减少一层循环,那么是否还能再减少一层循环呢?显然是可以的,用一层循环遍历出第一个数a,对于剩下的两个数,由于数组已经排好序了,只需要用两个指针去从数组的头和尾取数,只要找到的两个数和a相加等0即可。
AC代码
二分查找
点击查看代码
class Solution {
private int b_search(int[] nums, int low, int high, int num) {
while( low <= high ) {
int mid = ( low + high ) / 2;
if( nums[mid] == num ) {
return mid;
} else if( nums[mid] > num ){
high = mid - 1;
} else {
low = mid + 1;
}
}
return -1;
}
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
int len = nums.length;
if( len < 3 ){
return res;
}
Arrays.sort(nums);
for(int i=0; i<len; i++) {
if( i!=0 && nums[i-1]==nums[i] ) {
continue;
}
int last = i+1;
while( last < len-1 ) {
if( last > i+1 && nums[last-1]==nums[last] ) {
last ++;
continue;
}
int num = nums[i] + nums[last];
if( num > 0 ) {
break;
}
int ind = b_search(nums, last+1, len-1, num*-1);
if( ind!=-1 ) {
List<Integer> list = new ArrayList<>();
list.add(nums[i]);
list.add(nums[last]);
list.add(nums[ind]);
res.add(list);
}
last ++;
}
}
return res;
}
}
双指针
点击查看代码
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
int lasta = -100005;
int n = nums.length;
Arrays.sort(nums);
for(int i=0; i<n; i++) {
int a = nums[i];
if( lasta==a ) {
continue;
}
lasta = a;
int low = i+1;
int high = n - 1;
while( low < high ) {
int sum = a + nums[low] + nums[high];
if( sum>0 ) {
high --;
} else if( sum < 0 ) {
low ++;
} else {
List<Integer> list = new ArrayList<>();
list.add(a);
list.add(nums[low]);
list.add(nums[high]);
res.add(list);
while(low<high && nums[low]==nums[low+1]) {
low ++;
}
while(low<high && nums[high]==nums[high-1]) {
high --;
}
low ++;
high --;
}
}
}
return res;
}
}
低调做人,高调做事。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理