击败了90%的解法?Two Sum 从 O(n²) 到 O(n) 的优化之路

同样是 Two Sum,暴力解法耗时 56ms,而哈希解法仅需 2ms,差距在哪?

话不多说,先上图

下图为暴力解法

图1-1

下图为暴力解法的代码

js 复制代码
public class TwoSum {
    public int[] twoSum(int[] nums, int target) {
        // 外层循环:遍历每个元素作为第一个数
        for (int i = 0; i < nums.length; i++) {
            // 内层循环:遍历当前元素之后的所有元素(避免重复计算)
            for (int j = i + 1; j < nums.length; j++) {
                // 判断两数之和是否等于目标值
                if (nums[i] + nums[j] == target) {
                    // 找到则返回两个元素的下标
                    return new int[]{i, j};
                }
            }
        }
        // 题目假设一定有解,此处可根据实际需求返回null或抛出异常
        return null;
    }
}

下图为借助HashMap实现的

图1-3
下图为借助**HashMap**实现的代码

class 复制代码
    public int[] twoSum(int[] nums, int target) {
        HashMap<Integer,Integer>sumMap=new HashMap<>();
        //这里第一个Integer是nums[i]
        //第二个Integer是i(数组的索引值)
        for(int i=0;i< nums.length;i++){
            //这里的complement指的是目标值和当前遍历的值的差值
            int complement=target-nums[i];
            if(sumMap.containsKey(complement)){
                return new int[]{sumMap.get(complement),i};
            }
            //如果在sumMap中没有找到与nums[i]和为target的值
            // 那就把当前的值和对应的索引放在sumMap里,
            //为了给后面还没有遍历到的元素做匹配存储
            sumMap.put(nums[i],i);
        }
        return null;
    }
}

作为"小趴菜"的我第一眼看到这个题目,想到的就是暴力解法

这种方法容易想到而且好理解,但总觉得不对劲------如果数组很长,这代码岂不是要跑半天?比如说当数组长度 n=10⁵ 时,暴力解法需要计算 10¹⁰ 次,直接超时!而且效率极低!所以此方法绝不是最佳。其实这题藏着哈希表最核心的用法:用空间换时间,把"找元素"的效率从O(n)压到O(1)。

暴力解法 和利用HashMap解法的主要区别:

想找和为target的另一个数,其实就是找target - numsi。暴力法是一个个问(遍历),而哈希表像个"通讯录"------把见过的数和它的下标记下来,下次需要时直接查(不用再遍历)。比如 nums = 2,7,11,15,target=9:

  • 当i=0(numsi=2),需要找9-2=7,查通讯录(目前为空),就把2和下标0存进去;

  • 当i=1(numsi=7),需要找9-7=2,查通讯录------哎,2在里面!直接返回0,1

  • 图1-4中 map.containsKey(complement) :"这一步就是'查通讯录',时间复杂度O(1)";

下表展示两种解法复杂度区别以及使用场景

方法 时间复杂度 空间复杂度 适用场景
暴力循环 O(n²) O(1) 数组极短的情况(n<1k)
哈希表 O(n) O(n) 大部分场景(n>1w)

除了这两种解法,是否还有其他解法。

答案是肯定的

它就是"双指针解法"

但是使用这种解法是有前提的。已排序数组 是双指针优化的关键前提!如果题目给定的数组是升序排列 (如 [2, 7, 11, 15]),可以直接用双指针将时间复杂度优化到 O(n) ,且空间复杂度为 O(1)(无需额外哈希表)。

上代码:

`public int\[\] twoSum(int\[\] nums, int target) {

sql 复制代码
int left = 0, right = nums.length - 1;
while (left < right) {
    int sum = nums[left] + nums[right];
    if (sum == target) {
        return new int[]{left, right}; // 返回索引
    } else if (sum < target) {
        left++; // 和太小,左指针右移
    } else {
        right--; // 和太大,右指针左移
    }
}
return null; // 无解

}`

  • 时间复杂度 :O(n)
    • 双指针最多遍历整个数组一次(如最坏情况下 leftright 相遇)。
  • 空间复杂度 :O(1)
    • 仅用两个指针变量,无额外空间。

以下是三种解法复杂度表

解法 时间复杂度 空间复杂度 适用场景
暴力双重循环 O(n²) O(1) 无序数组,数据量小(n<1k)
哈希表 O(n) O(n) 无序数组,数据量大 (n>1w)
双指针 O(n) O(1) 已排序数组

一定要注意!!!使用双指针的前提是已排序的数组

最后关于三数之和的复杂度,想和掘友们聊聊:暴力是O(n³),排序+双指针是O(n²) ,理论上哈希表也能做(存两数和),但实际为啥很少用哈希法?是空间换时间不划算,还是去重逻辑太复杂?大家在项目里遇到类似三数问题,优先选哪种思路?

有任何疑问,或者有其他优化思路,欢迎在评论区讨论~

欢迎大佬们不吝赐教~

感谢观看!

相关推荐
小欣加油7 小时前
leetcode56 合并区间
c++·算法·leetcode·职场和发展
lqqjuly7 小时前
前沿算法深度解析(二)
人工智能·算法·机器学习
徐小夕8 小时前
万字长文!千万级文档 RAG 知识库系统落地实践
前端·算法·github
akunkuntaimei8 小时前
2026年高考数学各省真题及答案(完整版)
算法·高考
Hello:CodeWorld9 小时前
C 风格变参 vs C++ 变参模板:核心区别与选型指南
c语言·c++·算法
8Qi810 小时前
LeetCode 516:最长回文子序列
算法·leetcode·职场和发展·动态规划
youngerwang11 小时前
【从搬运工到协处理器:网卡芯片架构、算法、验证与边缘演进深度剖析】
网络·算法·架构·芯片
KaMeidebaby12 小时前
卡梅德生物技术快报|纯化重组蛋白实操详解
人工智能·python·tcp/ip·算法·机器学习
手写码匠13 小时前
从零实现 Prompt 工程引擎:结构化提示、自动优化与多轮自省体系
人工智能·深度学习·算法·aigc
无限码力13 小时前
阿里算法岗 0530笔试真题 - 多约束条件下的元素匹配统计
算法·阿里笔试真题·阿里机试真题·阿里算法岗笔试