数组算法题1:两数之和(LeetCode01)

目录

1、解题三部曲

1.1、 看懂题目

1.2、分析,推导解法

1.3、将思路转换为代码

总结

2、题目

3、解题过程


两数之和(LeetCode01:Array And HashMap)

相关文章:[LeetCode] Two Sum 两数之和

1、解题三部曲

在具体做题的时候,可以采用以下三个步骤来进行。

拿到题目后,不要立马开干,想着下面的三个步骤,一步一步地来。

1.1、 看懂题目

看懂题目。有的题目很直接,直接告诉你要解决的问题是什么,题目本身甚至都包含了对应的数据结构和需要用到的算法;有的题目很隐晦,看了半天不知道它到底要解决什么问题,可以用什么算法和数据结构来解。所以,看到题目后,一定要先确保自己理解清楚了。

我的一个经验是,拿到一个题目后,看5分钟,如果5分钟之内看不懂,我就mark 下来,留到后面再做,要不很影响刷题的心情。

不过就leetcode 来说,这样的题目不多。基本都能在再5分钟内看懂。

1.2、分析,推导解法

分析推导题目的解法。

这个步骤要有意识地单独拎出来,不要跟编码步骤混淆在一起。也就是说,你在分析推导题目解法的时候,不要去想任何实现相关地事情,不用去想代码怎么写,不用去想要用什么库,定义什么变量,用多少层循环,都不要想,就想着在逻辑上,这道题目要怎么解。

这样做可以极大地降低你的心智负担,使你高效地想出题目的解法。对于如何将想法变成代码,可以留在下一个步骤,单独来进行。

1.3、将思路转换为代码

当你确定题目都已经理解,并且分析推导出了题目的解法后,你才开始来思考如何将自己的思路转换成代码。是地,将思路转换成代码,可以是一个单独地步骤,在实际工作中,其实也是很重要的一个能力。

有时,将一个思路转换成算法是很容易且自然的;但有时,有些思路转换成代码,是很有难度的事情。

或者你有体会,分析推导只用了不到十分钟,结果代码写了半小时还写不完整。

怎么定义变量,保存状态,用递归,还是用循环加辅助数据结构等等,都是将思路转换成代码要做的事情。

这个能力也需要刻意地去练习。

总结

首先算法不是只拼智商的,是可以通过后天的刻意练习掌握的一种能力。

刚上手的时候,难度上需要循序渐进,最好能够按算法分类来刷题。

解题的时候,建议按这三个步骤来

1,看懂题目

2,分析,推导解法

3,将思路转换为代码。

在更细节方面,封装的思想也可使用在算法上面,可以极大地降低我们的心智负担,提升解题的效率。

最后是要注意做题过程中的正反馈,确保自己能持续地做下去。

2、题目

题目来源:https://leetcode-cn.com/problems/two-sum/

两数之和  Two Sum

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

你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。

示例 1:

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例 2:

输入:nums = [3,2,4], target = 6
输出:[1,2]
示例 3:

输入:nums = [3,3], target = 6
输出:[0,1]
 

提示:

2 <= nums.length <= 104
-109 <= nums[i] <= 109
-109 <= target <= 109
只会存在一个有效答案
进阶:你可以想出一个时间复杂度小于 O(n2) 的算法吗?

3、解题过程

这道题给了我们一个数组,还有一个目标数target,让我们找到两个数字,使其和为target,乍一看就感觉可以用暴力搜索,但是猜到OJ肯定不会允许用暴力搜索这么简单的方法,于是去试了一下,果然是Time Limit Exceeded,这个算法的时间复杂度是O(n^2)。

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

    public static void main(String[] args) {
        int[] res = twoSum(new int[]{2, 7, 11, 15}, 9);
        System.out.println();
    }
}

那么只能想个O(n)的算法来实现,由于暴力搜索的方法是遍历所有的两个数字的组合,然后算其和,这样虽然节省了空间,但是时间复杂度高。一般来说,我们为了提高时间的复杂度,需要用空间来换,这算是一个trade off吧,我们只想用线性的时间复杂度来解决问题,那么就是说只能遍历一个数字,那么另一个数字呢,我们可以事先将其存储起来,使用一个HashMap,来建立数字和其坐标位置之间的映射,我们都知道HashMap是常数级的查找效率,这样,我们在遍历数组的时候,用target减去遍历到的数字,就是另一个需要的数字了,直接在HashMap中查找其是否存在即可,注意要判断查找到的数字不是第一个数字,比如target是4,遍历到了一个2,那么另外一个2不能是之前那个2,整个实现步骤为:先遍历一遍数组,建立HashMap映射,然后再遍历一遍,开始查找,找到则记录index。代码如下:

Java 解法一:

class Solution2 {
    public static int[] twoSum(int[] nums, int target) {
        Map<Integer, Integer> map = new HashMap<>();
        int[] res = new int[2];
        for (int i = 0; i < nums.length; i++) {
            if (map.containsKey(target - nums[i])) {
                res[0] = i;
                res[1] = map.get(target - nums[i]);
                break;
            }
            map.put(nums[i], i);
        }
        return res;
    }

    public static void main(String[] args) {
        int[] res = twoSum(new int[]{2, 7, 11, 15}, 9);
        System.out.println(res[0]);
        System.out.println(res[1]);
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值