leetcode 1 两数之和

本菜鸡在查阅力扣的解答参考资料时感觉其往往缺乏展示思考的过程,没有从简单解法到复杂解法的演化。只是一股脑丢出最优解,让人略感痛苦,因此写下这个博客,如有错误,望不吝赐教

问题描述

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

注意:同一个元素不能使用两次

问题分析

要找到两个数组元素之和为目标值的元素位置,至少要将数组遍历一遍。容易想到,可以依次以数组的每一个元素作为第一个加数——a[i],再在剩余的元素中依次查找a[j] = target - a[i],j ≠ \neq =i


class Solution {

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

    int [] res = new int [2];

    for(int i = 0; i < nums.length; i++){

        int leftVal = target - nums[i];

        for(int j = 0; j < nums.length; j++){

            if(i != j && nums[j] == leftVal){

                res[0] = j;

                res[1] = i;

                break;

            }

        }

    }

    return res;

    }

}

结果

在这里插入图片描述

结果分析

可以看出,执行速度较慢。基于该方法进行优化。可以看到内层循环是数组开头寻找,这一步有冗余

因为,如果在k ∈ \in {0,j - 1}的范围存在a[k] = target - a[j]的话,在i = k的时候就已经能得到结果了(k < j)

因此二层循环以 i + 1的值做为起始索引。需要修改的地方如下所示


 for(int j = i + 1; j < nums.length; j++)

结果

在这里插入图片描述

时间更短

进一步优化

我们发现主要的耗时用在了查找第二个加数上面。而查找算法可以使用HashMap来优化,哈希表可以在O(1)时间内搜索目标值

遍历数组,先判断在哈希表中有没有key = target - a[i]的存在

如果有, 查找结束,将该key对应的value拿出加入到结果数组中,将 i 也加入到结果数组中

如果没有,将(key , value) = (a[i] , i)


class Solution {
    public int[] twoSum(int[] nums, int target) {
        if(nums == null)
            return null;
        int [] res = new int[2];
        for(int i= 0; i< nums.length;i++){
            int leftValue = target - nums[i];
            for(int j = i+ 1; j < nums.length; j++){
                if(nums[j] == leftValue) {
                    res[0] = i;
                    res[1] = j;
                    return res;
                }
            }
        }
        return res;
    }
}

###结果

在这里插入图片描述

可以看出,时间损耗大大降低由原来的O(n^2)降低为O(2)

总结

做题目时,可以先从最简单的暴力求解做起。时间消耗过高时,先尝试对本方法的优化。再考虑用新的方法解决

本题的答案是通过两次优化得到的,主要的优化点是哈希表对搜索的时间的优化,但是空间复杂度上升为O(n)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值