第一天:两数之和

Day1

刷题第一天,不知道自己可以坚持几天,慢慢来。。
PS:这是我第一次写博客,有很多不足的地方,很多地方也没有说的很清楚,没有把我想表达的东西表达出来,希望大家见谅!

题目描述

两数之和:给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
原题地址点这里

解法一

最开始看到这道题我的想法就是直接两层循环一个个来查找。思路非常简单,代码如下:

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        int length = nums.size();
        vector<int> result;
        for(int i=0; i<length; i++) {
            for(int j=i+1; j<length; j++) {
                if(nums[i] + nums[j] == target) {
                    result.push_back(i);
                    result.push_back(j);
                }
            }
        }
        return result;
    }
};

提交结果

解法二

正所谓精益求精,可以明显看到解法一耗费的时间和空间都非常大,因此这显然不是一个好的解法,那我们要怎么改进呢?
通过观察解法一的代码,我们发现主要是两层循环需要耗费大量的时间,因为这是一个O(n2)时间复杂度的算法,因此我们需要想办法降低他的时间复杂度。那么我们要怎么做呢?请看下面的代码:

class Solution {
	public:
    	vector<int> twoSum(vector<int>& nums, int target) {
        	vector<int> result(2);
        	vector<int> temp(nums);
        	sort(temp.begin(), temp.end());
        	int length = nums.size();
	        int i=0, j=length-1;
        	while((temp[i]+temp[j]!=target) && (i<j))
        	{
            	if(temp[i]+temp[j] > target) j--;
            	else i++;
        	}
        	result[0] = search_index(nums, temp[i], -1);
        	result[1] = search_index(nums, temp[j], result[0]);
        	return result;
    	}
    	int search_index(vector<int> nums, int value, int flag){
       		int j = nums.size();
        	int index = 0;
        	for(int i=0; i<j; i++) {
            	if(nums[i] == value) {
                	if(i != flag) {
                		index =  i;
                		}
                	}
                }
            }
        return index;
    }
};

我们先是创建了一个给定vector的副本,之后对其进行由小到大排序,之后用最小的元素(排序后vector的第一个元素)加上最大的元素(排序后vector的最后一个元素),如果他们的和大于要找的target,那么就把最后一个元素的下标往前移;反之,若是小于则把第一个元素的下标往后移,直到找到等于target为止。
我在网上的一些地方也看到了类似的方法,他们把它称为“首尾递进查找”,我也不太记得我当时是怎么想到这个方法的了,也许是借鉴了其他人的想法。最后贴一张提交截图。
这是当时第一次做的时候提交记录:
提交截图
这是我最近提交的,同样的代码不知道为什么时间差距这么大。。。。但是比起解法一,进步还是蛮大的。
提交截图

解法三

这个方法是我看了LeetCode官方给出的答案,不得不说我还是太嫩了,简而言之就是。话不多说,上代码:

class Solution {
    public int[] twoSum(int[] nums, int target) {
        Map<Integer, Integer> map = new HashMap<>();
        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 two sum solution");
    }
}

这种方法就是巧妙的利用了哈希表查找时很低的时间复杂度(O(1)),只需要一次遍历即可找到这两个目标元素的下标,实在是妙啊。附上提交截图:
提交截图
可以发现,虽然时间非常少,但是空间开销还是特别大的,因为哈希表需要耗费较多的空间资源吧,这也是一种空间换时间的方法。

总结

这只是Leet Code上一道十分简单的题目,但是想把它做好还是有一点难度的,不得不说算法这个领域真是博大精深,希望大家一起努力,一起进步!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值