三数之和 Leecode 2024/12/02
思路:1. 找到所有不重复下标的整数组合。2. 在所有组合中找到和为0的组。
暴力解法超时!!!
public static List<List<Integer>> threeSum(int[] nums) {
int num_len = nums.length;
HashSet<List<Integer>> rs = new HashSet<>();
for (int i = 0; i < num_len-2; i++){
for (int j = i+1; j < num_len-1; j++){
for (int k = j+1; k < num_len; k++){
if (nums[i] + nums[j] + nums[k] == 0){
// 将 HashSet 转换为 List
List<Integer> list = new ArrayList<>();
list.add(nums[i]);
list.add(nums[j]);
list.add(nums[k]);
list.sort(null);
rs.add(list);
}
}
}
}
List<List<Integer>> result = new ArrayList<>(rs);
return result;
}
排序 + 双指针
先将 nums 排序,时间复杂度为 O(NlogN)。
固定 3 个指针中最左(最小)元素的指针 k,双指针 i,j 分设在数组索引 (k,len(nums)) 两端。
双指针 i , j 交替向中间移动,记录对于每个固定指针 k 的所有满足 nums[k] + nums[i] + nums[j] == 0 的 i,j 组合:
当 nums[k] > 0 时直接break跳出:因为 nums[j] >= nums[i] >= nums[k] > 0,即 3 个元素都大于 0 ,在此固定指针 k 之后不可能再找到结果了。
当 k > 0且nums[k] == nums[k - 1]时即跳过此元素nums[k]:因为已经将 nums[k - 1] 的所有组合加入到结果中,本次双指针搜索只会得到重复组合。
i,j 分设在数组索引 (k,len(nums)) 两端,当i < j时循环计算s = nums[k] + nums[i] + nums[j],并按照以下规则执行双指针移动:
当s < 0时,i += 1并跳过所有重复的nums[i];
当s > 0时,j -= 1并跳过所有重复的nums[j];
当s == 0时,记录组合[k, i, j]至res,执行i += 1和j -= 1并跳过所有重复的nums[i]和nums[j],防止记录到重复组合。
public static List<List<Integer>> threeSum(int[] nums) {
// 1. 排序
Arrays.sort(nums);
int num_len = nums.length;
List<List<Integer>> result = new ArrayList<>();
// 2. 双指针遍历
for (int i = 0; i < num_len - 2; i++) {
int j = i+1, k = num_len - 1;
if (i > 0 && nums[i] == nums[i-1]) continue; // 本次双指针搜索只会得到重复组合
if (nums[i] > 0) continue; //在此固定指针 i 之后不可能再找到结果了
while(j < k){
int s = nums[i] + nums[j] + nums[k];
if (s == 0) {
List<Integer> temp = new ArrayList<>();
temp.add(nums[i]);
temp.add(nums[j]);
temp.add(nums[k]);
result.add(temp);
// 跳过重复的元素
while (j < k && nums[j] == nums[j + 1]) j++;
while (j < k && nums[k] == nums[k - 1]) k--;
k--;
j++;
} else if (s > 0) {
k--;
} else {
j++;
}
}
}
return result;
}
原文地址:https://blog.csdn.net/skyxya/article/details/144213140
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!