Leetcode #1 Two Sum续

昨天,我提交成功了第一道leetcode,用的最简单的暴力法,但也很开心了。今天,我想再来学习一下另外两种使用哈希表的方法,之所以想做leetcode就是因为一道题能学习到多种解法,这种感觉很安逸。

在昨日简单学习了vector的基础上,这次需要用到unordered_map,即无序关联容器,它有一个键值(key value)和一个索引值(mapped value),就好像是函数映射x对应f(x)一样,无序的(unordered)相比正常map,根据其键值能更快检索(retrieve)到需要的数据。


先说过两遍哈希表:

vector<int> twoSum(vector<int>& nums, int target) {
	vector<int> res;
	unordered_map<int, int> m;
	for (int i=0;i<nums.size();i++) {
		m[nums[i]]=i;//m[2]=0 m[7]=1 m[11]=2 m[15]=3
	}
	for (int i=0;i<nums.size();i++) {
		int t=target-nums[i];
		if (m.count(t)&&m[t]!=i) {
			res.push_back(i);
			res.push_back(m[t]);
			break;
		}
	}
	return res;
}

时间复杂度:O(n) 没有嵌套的for了

空间复杂度:O(n) 取决于哈希表中元素的数量,有n个,课上常听说的空间换时间。

  1. unordered_map<int, int> m:前面一个int是键值的类型,后面一个int是索引值的类型,很神奇的是它跟string一样大小都是自动变的,所以不用担心超过范围。
  2. m[nums[i]]=i:testcase测试的数据nums[]={2,7,11,15}有4个元素,按照2-0,7-1,11-2,15-3的映射关系把nums的4个元素装进m这个无序关联容器,别看索引值是0,1,2,3,这个无序指的是键值之间无序,这很关键,这种容器就看准键值进行检索,所以很快。执行完之后容器内部就得到了m[2]=0,m[7]=1,m[11]=2,m[15]=3的关系。
  3. m.count(t):返回容器中键值与t相同的元素的数量。
  4. m.count(t)&&m[t]!=i:需要两个条件同时成立,一个条件是与nums[i]相加得到target值的另一个数t能在m容器中存在,另一个条件是一个数不能用两次。满足这两个条件就可以把对应的两个数的indices存入返回的res容器了。
  5. break:刚开始我还担心会把同组数据存两次,或者有多组符合条件的数据的话怎么样呢,还好题目说明了明确只有一个solution,既然找到了就快逃出循环吧。

接下来是一遍哈希表:

vector<int> twoSum(vector<int>& nums, int target) {
	unordered_map<int, int> m;
	for(int i=0;i<nums.size();i++){
		if(m.count(target-nums[i])){
			return { i, m[target-nums[i]] };
		}
		m[nums[i]]=i;
	}
	return {};
}

其实也差不多,换汤不换药,就是把第一遍构成哈希表的步骤省去了,然后直接判断m中有没有满足条件的键值(第一次循环肯定没有啦,没有一个元素在哈希表里建立了映射关系),如果找到了就直接return符合条件的index i和键值对应的索引值m[target-nums[i]],否则就把num[i]中的这个元素当作键值装进哈希表,以便后面来的匹配。最后真的一个没找到的话,注意twoSum是一个vector容器,不能return 0,而是空集合{}。


再附下加了main的完整的cpp代码,满足下我的强迫症

#include <iostream>
#include <cstdio>
#include <vector>
#include <unordered_map>

using namespace std;

vector<int> twoSum(vector<int>& nums, int target) {
	vector<int> res;
	unordered_map<int, int> m;
	for (int i=0;i<nums.size();i++) {
		m[nums[i]]=i;//m[2]=0 m[7]=1 m[11]=2 m[15]=3
	}
	for (int i=0;i<nums.size();i++) {
		int t=target-nums[i];
		if (m.count(t)&&m[t]!=i) {
			res.push_back(i);
			res.push_back(m[t]);
			break;
		}
	}
	return res;
}

int main() {
	vector<int> nums;
	nums.push_back(2);//nums=[2]
	nums.push_back(7);//nums=[2,7]
	nums.push_back(11);//nums=[2,7,11]
	nums.push_back(15);//nums=[2,7,11,15] nums.size()=4
	vector<int> a=twoSum(nums, 9);
	cout<<a[0]<<" "<<a[1];
}

有一个问题是,不知道为什么过一遍哈希表的代码在leetcode上accepted了但我的软件上就出错了。。。

 


 

 

 

 

 

 

 

 

 

这种博客其实算是我给自己在讲思路。但我相信天天游戏的P神如果哪天突然想编程的话还是可以来看看这类博客的。。。天色不早。

(逃)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值