LeetCode - 0001 两数之和

题目地址:https://leetcode.cn/problems/two-sum/description/

:你好,面试官,我对算法了解的不多,只刷过LeetCode第一题,你不要问的太难了,好,我准备好了。

面试官:啊?这?你的胆子很大呀,这也行,真的是初生牛犊不怕虎,好吧,那我就问问你LeetCode第一题,题目如下:

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

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

示例 :

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

输出:[0,1]

解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

好,题目明白了吗?请开始你的表演🙂


:好的,面试官,题目我明白了,其实这个问题很简单,两个嵌套for循环搞定。外层循环用来遍历数组中的元素,而内层循环则用来与当前元素后面的元素进行比较,为了避免重复计算,我们让外层循环的 i i i 从 0 开始,到 n − 2 n−2 n2 结束(为了确保内层循环 j j j 能取到数),内层循环从 i + 1 i+1 i+1 开始,到 n − 1 n−1 n1 结束。其中时间复杂度为 O ( N 2 ) O(N^2) O(N2)

public int[] twoSum(int[] nums, int target) {
    int n = nums.length;
    for (int i = 0; i < n - 1; i++) {
        for (int j = i + 1; j < n; j++) {//内层循环只遍历i后面的数
            if (nums[i] + nums[j] == target) {
                return new int[]{i,j};
            }
        }
    }
    return new int[]{};
}

面试官:面试官撇了撇嘴,不厌其烦的说,可以嘛,还能够想到内层循环从i+1开始,而不是从0开始。

:我笑了笑,嘿嘿,是的,避免了重复计算。其实…

​ 我正要往下说,面试官打断了我

面试官:但是,你不觉得你这样时间复杂度太高了吗? O ( N 2 ) O(N^2) O(N2),你可以降低它的时间复杂度吗,还有没有其他的解法呢?

:可以的,其实我们想减少时间复杂度,不外乎就是降低其重复的操作,在上面的嵌套循环中,我们可以发现内层循环在遍历 i i i 后面的数时,有的数是被重复扫描了多次的,所以我们可以先把数组遍历一次,把结果先放一边,我们可以用一个哈希表存起来,key为数值,value为数值的下标,第二次遍历的时候再去哈希表里面查找有没有符合条件的数。

​ 一分钟后,我写好了代码

class Solution {
    public int[] twoSum(int[] nums, int target) {
        HashMap<Integer, Integer> map = new HashMap();
        // 遍历一次将数放入map
        for (int i = 0; i < nums.length; i++) {
            map.put(nums[i], i);
        }
        for(int i = 0; i < nums.length;i++){
            int one = nums[i]; // 第一个数
            int two = target - one;// 第二个数
            if(map.containsKey(two)){// 在map中查找是否有数b
                return new int[]{i,map.get(two)};
            }
        }
        return new int[]{};
    }
}

面试官:我看看,咦~~~,确实减少了遍历次数,降低了时间复杂度。哎,不对呀,如果我这里给你数组 n u m s = [ 3 , 2 , 4 , 1 ] nums=[3,2,4,1] nums=[3,2,4,1],目标值target为6,你这个得到的结果是 [ 0 , 0 ] [0,0] [0,0]

:我连忙看了看代码,说到,额,好像是有点问题,这里我们好像在遍历的时候,把当前的数从哈希表中移除掉,于是修改了下第二个循环的代码

for(int i = 0; i < nums.length;i++){
    int one = nums[i]; // 第一个数
    int two = target - one;// 第二个数
    if(map.get(one) == i) map.remove(one);
    if(map.containsKey(two)){// 在map中查找是否有数two
        return new int[]{i,map.get(two)};
    }
}

面试官:嗯,这样就对了

​ 面试官沉默了一会儿

面试官:你看你上面写的代码还要去删除map里面的值,我们可不可以这样,比如我们在遍历数组时,一边遍历,一边将数存入哈希表,比如对于 n u m s [ i ] nums[i] nums[i],这个数,再从哈希表中去找有没有 t a r g e t − n u m s [ i ] target-nums[i] targetnums[i] 这个数,如果没有,再把 n u m s [ i ] nums[i] nums[i] 这个数加入到map中,会不会更好些呢,你想想。

​ 听了面试官的提示,我想了想

:O,好像是可以这么做!

面试官:来,按照这个思路,写下代码呢

:en,好,首先在遍历的时候…,心里面一边嘀咕,一边在纸上写代码

class Solution {
    public int[] twoSum(int[] nums, int target) {
        HashMap<Integer, Integer> map = new HashMap();

        for (int i = 0; i < nums.length; i++) {
            int one = nums[i]; // 第一个数
            int two = target - one;// 第二个数
            if (map.containsKey(two)) {// 在map中查找是否有数two
                return new int[] { i, map.get(two) };
            }
            map.put(one, i);// 找不到再put
        }
        return new int[] {};
    }
}

:写好了,你看看呢

面试官:对对对,这样就避免了我们去删除哈希表的操作,时间复杂度也降到了 O ( N ) O(N) O(N)

​ 此时,面试官的手机铃声响了

面试官:五点半了,下班了,我们该天再面哈😁

:好的,好的,(居然还有这种操作,真的是准时下班)

  • 11
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值