解密N数之和问题的秘密

目录

两数之和

我们来看力扣第一题

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

示例 1:

输入:nums = 2,7,11,15, target = 9

输出:0,1

解释:因为 nums0 + nums1 == 9 ,返回 0, 1

示例 2:

输入:nums = 3,2,4, target = 6

输出:1,2

示例 3:

输入:nums = 3,3, target = 6

输出:0,1

这个题我们看到之后想到最简单的思路就是两个for循环,里层数加外层数之和等于目标数,我们就返回两个下标。

java 复制代码
  public int[] twoSum(int[] nums, int target) {
        // 遍历数组
        for (int i = 0; i < nums.length; i++) {
            // 内层循环从i+1开始,因为i已经试过
            for (int j = i+1; j < nums.length; j++) {
                // 如果两个数相加等于target,则返回下标
                if(nums[i] + nums[j] == target){
                    return new int[]{i,j};
                }
            }
        }
        // 如果没有找到,则返回空数组
        return new int[0];
    }

但是这个解法的时间复杂度很高,我们还有更好的方法就是使用哈希表,这种方式我们可以把寻找target-x的时间复杂度由O(N)变为O(1)。

对于每一个x,我们可以先在哈希表中查找是否存在target-x,如果不存在即可把x放入哈中,这样可以避免与自己相遇。

代码实现如下:

java 复制代码
public int[] twoSum1(int[] nums, int target) {
        // 创建一个HashMap
        HashMap<Integer,Integer> map =  new HashMap<>();
        // 遍历数组
        for (int i = 0; i < nums.length; i++) {
            // 如果HashMap中包含target-nums[i],则返回该值和i
            if(map.containsKey(target - nums[i])){
                return new int[]{ map.get(target-nums[i]),i};
            }
            // 将nums[i]作为key,i作为value,放入HashMap中
            map.put(nums[i],i);
        }
        // 如果没有找到,则返回一个空数组
        return new int[0];
    }

三数之和

我们来看力扣15题的描述

给你一个整数数组 nums ,判断是否存在三元组 nums\[i, numsj, numsk] 满足 i != j、i != k 且 j != k ,同时还满足 numsi + numsj + numsk == 0 。请

你返回所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例 1:

输入:nums = -1,0,1,2,-1,-4

输出:\[-1,-1,2,-1,0,1]

解释:

nums0 + nums1 + nums2 = (-1) + 0 + 1 = 0 。

nums1 + nums2 + nums4 = 0 + 1 + (-1) = 0 。

nums0 + nums3 + nums4 = (-1) + 2 + (-1) = 0 。

不同的三元组是 -1,0,1-1,-1,2

注意,输出的顺序和三元组的顺序并不重要。

示例 2:

输入:nums = 0,1,1

输出:\[\]

解释:唯一可能的三元组和不为 0 。

示例 3:

输入:nums = 0,0,0

输出:\[0,0,0]

解释:唯一可能的三元组和为 0 。

这道题使用三个for循环时间复杂度太高了不可取,我们使用排序加双指针来做这道题。

java 复制代码
 public List<List<Integer>> threeSum(int[] nums) {
        int n = nums.length;
        Arrays.sort(nums);
        List<List<Integer>> ans = new ArrayList<>();
        //枚举a
        for (int first = 0; first < n; first++) {
            //和上一次的枚举数不相同
            if (first > 0 && nums[first] == nums[first - 1]) {
                continue;
            }
            int third = n - 1;
            int target = -nums[first];
            //枚举b
            for (int second = first + 1; second < n; second++) {
                if (second > first + 1 && nums[second] == nums[second - 1]) {
                    continue;
                }
                //保证b的指针在c的指针的左侧
                while (second < third && nums[second] + nums[third] > target) {
                    third--;
                }
                if (second == third) {
                    break;
                }
                if (nums[second] + nums[third] == target) {
                    List<Integer> list = new ArrayList<>();
                    list.add(nums[first]);
                    list.add(nums[second]);
                    list.add(nums[third]);
                    ans.add(list);
                }
            }

        }
        return ans;
    }
  1. 首先,对输入的数组进行排序。这样可以保证在后续的查找过程中,相邻的元素是有序的,便于排除重复的情况。
  2. 初始化一个空的答案列表,用于存储满足条件的三元组。
  3. 枚举数组的第一个元素作为第一个指针(a),第二个元素作为第二个指针(b),最后一个元素作为第三个指针(c)。
  4. 在枚举a的过程中,如果发现a和上一次枚举的元素相同,则跳过此次循环,继续枚举下一个不同的元素。
  5. 在枚举b的过程中,如果发现b和上一次枚举的元素相同,则跳过此次循环,继续枚举下一个不同的元素。
  6. 在枚举b的过程中,保证b的指针在c的指针的左侧。
  7. 当b指针小于c指针时,判断当前元素之和是否等于目标值。如果等于目标值,则将当前三元组添加到答案列表中。
  8. 继续枚举a和b,直到所有可能的组合都被检查完毕。
  9. 返回答案列表。

还有更多好玩的题目例如:四数之和等等。

相关推荐
卷福同学4 小时前
不用服务器,不用配环境,我10分钟上线了一个AI Agent
人工智能·后端·算法
码兄科技6 小时前
Java AI智能体开发实战:从零构建智能对话系统指南
java·开发语言·人工智能
折哥的程序人生 · 物流技术专研6 小时前
第8篇:六大设计原则在工厂模式中的体现
java·设计模式·设计原则·工厂模式·编程进阶·扩充系列
问君能有几多愁~6 小时前
C++ 数据结构复习笔记
数据结构·c++·笔记
至乐活着7 小时前
深入解析跳表SkipList:原理、实现与性能优化实战
数据结构·算法·跳表·skiplist·java实现
小明bishe187 小时前
计算机毕业设计之基于JAVA的植物科普网站
java·spring boot·spring·架构·课程设计
r_oo_ki_e_7 小时前
Java Map 集合学习笔记
java·笔记·学习
SL-staff7 小时前
智慧园区2000+设备统一管理:JVS-IoT如何降低运维成本40%
java·开发语言·物联网·智慧园区·设备管理·运维优化·jvs-iot
Jerry7 小时前
LeetCode 383. 赎金信
算法
ai产品老杨8 小时前
H264 H265视频分析常见问题和排查清单
人工智能·算法·音视频