LeetCode第1题思悟——两数之和(Two Sum)

吃一堑也不一定长一智,但是对吃一堑的反思可以长一智!

第一题

1. 题目要求

Given an array of integers, return indices of the two numbers such that they add up to a specific target.

You may assume that each input would have exactly one solution, and you may not use the same element twice.
(给定一个整数数组和一个目标值,找出数组中和为目标值的两个数。
你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用。)

2. 示例

给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

3. 我的思路

首先,要在一个数组中找到两个数和为指定值,那么我可以遍历一遍该数组,每次访问数组中的一个数,然后这个问题就转换为在剩余的元素里查找特定值(target-currentElement,其实是一个二重遍历了);自然是一个嵌套循环;代码实现也比较简单(就不加注释了,不能为了注释而注释,我的C#老师说,好的编程分格可以替代不少注释~ ,感觉通过变量名是可以明白思路的,毕竟是我是小白一个嘛~):

	public int[] twoSum(int[] nums, int target) {
        	int firstNum;
        	int secondNum;
        	int targetNum;
        	int[] results=new int[2];
        	int numbersLength=nums.length;
        	for(int i=0;i<numbersLength;i++){
            		firstNum=nums[i];
            		targetNum=target-firstNum;
            		for(int j=i+1;j<numbersLength;j++){
                		secondNum=nums[j];
                		if(secondNum==targetNum){
                    			results[0]=i;
                    			results[1]=j;
                    			break;
                		}
            		}
        	}
        	return results;
    }

好的,没问题,可以通过(不通过我也不记在这里呀,但只是通过而已——29ms,超过40%的Java提交);这里的思悟是来源于我没有通过的版本:

  1. 第一次没有通过是因为内层循环变量j我写成i了(好吧,我承认我不是很习惯离开IDE写代码,但我正在努力尝试);
  2. 第二次没有通过是因为results[0]=firstNum;人家要的是索引,我返回的是值!(我承认这是因为我没有仔细看示例)

这两次都是因为“粗心”的原因,其实我知道“粗心”反映出的是我的编程习惯、处理问题的态度和方式上的缺陷。

4. 大神的解法

//运行时间7ms
	public int[] twoSum(int[] nums, int target) {
        Map<Integer,Integer>map=new HashMap<Integer,Integer>();
        for(int i=0;i<nums.length;i++){
            int complement=target-nums[i];
            if(map.containsKey(complement)){
                return new int[] {map.get(complement),i};
            }
            map.put(nums[i],i);
        }
        throw new IllegalArgumentException("no such two numbers");
    }
//运行时间6ms
	public int[] twoSum(int[] nums, int target) {
        Map<Integer,Integer> thisMap = new HashMap();
        for(int i=0;i<nums.length;i++){
            int tempTarget = target - nums[i];
            if(thisMap.size()!=0 && thisMap.get(tempTarget) != null){
                return new int[]{i,thisMap.get(tempTarget)};  
            }
            thisMap.put(nums[i],i);
        }
        return null;
    }
//运行时间5ms
	public int[] twoSum(int[] numbers, int target) {
        int [] res = new int[2];
        if(numbers==null||numbers.length<2)
            return res;
        HashMap<Integer,Integer> map = new HashMap<Integer,Integer>();
        for(int i = 0; i < numbers.length; i++){
            if(!map.containsKey(target-numbers[i])){
                map.put(numbers[i],i);
            }else{
                res[0]= map.get(target-numbers[i]);
                res[1]= i;
                break;
            }
        }
        return res;
    }

其实5-7ms的差距并不是很大,而且可以看出他们的共同点是:

  1. 使用了HashMap这一数据结构;
  2. 因为使用了HashMap这一数据结构,不管数据是什么样的,他们都只需一遍遍历即可!

5. 我和大神的差距在哪里

首先,从看待问题的角度来说,我是将问题转换为对一个数的查找;而大神们的解法其核心是记录(加入HashMap)+判断(是否已找到解);而判断是利用HashMap的高效查找特性完成的!比我的循环+比较高了不知多少;
其次,算法之所以差(和好的比~ )一定是做了一些重复而无用的事情,浪费了时间(这就是少死脑细胞的代价吧~)。我多做了什么呢?我把嵌套遍历中的内循环给浪费了!我的目光在于一个特定的数,但是实际上我已经遍历了整个数组,也就是如果说我的内循环没有找到答案,那么这次循环对于我解决这个问题的作用就是0,而甚至我的外层循环在找到答案之前的遍历也是毫无价值!差的22ms就是这么被我浪费的;而大神们的解法中,当找不到解时,也可以为下一次找到解做出贡献!——每一次访问数组都是有价值的!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值