小白跟随卡哥刷题第八天(hash表部分)

一、前言

今天是进入hash表的第二天,难度开始有点提升了,我也深入学习了一些以前并不太接触也不太重视的知识点,今天就接着这道题深入的讲一讲我的心得吧。题目很基础,但是我感觉解法也是比较多样的,当然最优解的方法卡哥已经给出了详细的解释,请各位uu自己看吧。

二、题目(力扣第349—两个数组的交集. - 力扣(LeetCode)

给定两个数组 nums1 和 nums2 ,返回 它们的 交集

 输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。

示例 1:
输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2]

示例 2:

输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[9,4]
解释:[4,9] 也是可通过的

三、题解

这个题卡哥的解答我先放在这里了(代码随想录)请各位uu写不出来或者想要看看更好的算法时自行去看吧,我重点说说我的思路。我个人认为其实向量或者说数组也是可以解决这道题的,而且也是比较好懂的,话不多说,直接上代码吧。

(1)数组解法

先是完整的代码如下:

vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
	vector<int> vec1(1000);//定义两个向量(数组)来存放nums1、nums2的元素
	vector<int> vec2(1000);
	vector<int> vec;//用来存放最后的结果(也就是交集元素)
	int len1=nums1.size();//得到nums1、nums2的长度
	int len2=nums2.size();
	for(int i=0;i<len1;i++){//将nums1中的元素存入vec1
		vec1(nums1[i])++;
	}
	for(int i=0;i<len2;i++){//将nums2中的元素存入vec2
		vec2(nums2[i])++;
	}
	for(int i=0;i<1000;i++){//求交集
		if((vec1[i]!=0)&&(vec2[i]!=0)){//若vec1和vec2中有交集
			vec.push_back(i);//使用push_back函数增加vec长度
		}}
	return vec;
}

接下来就详细讲讲这个代码:

这里的vec1和vec2,是直接定义了大小,默认初值为0,而vec并没有定义大小这与后面vec使用push_back函数来增加长度是对应的,否则的话力扣的编译是会报错的,因为你在声明vector容器的时候没有指定大小造成空指针。

    vector<int> vec1(1000);
	vector<int> vec2(1000);
	vector<int> vec;

接下来是整个算法最重要的地方:

这里的思路有点像昨天的题目中的,将nums对应的数值按照位置存入vec中,比如,nums[0]=5,则存入vec数组时,vec[nums[0]]++=vec[5]++;意思就是在下标为5的位置的值+1;从vec来看就是5这个数字出现了一次。如果此时nums[1]=5,那么vec[nums[1]]++,此时vec[5]的值就变成2了,意思就是5这个数字出现了两次。因此我只要把nums1、nums2的元素存入vec1、vec2中变成相应位置及次数即可。

for(int i=0;i<len1;i++){//将nums1中的元素存入vec1
		vec1(nums1[i])++;
	}
	for(int i=0;i<len2;i++){//将nums2中的元素存入vec2
		vec2(nums2[i])++;
	}

在同时比较vec1、vec2中相同位置是否为0,若不为0则说明两个数组中都出现过该元素(交集元素),则存入vec中即可。同时注意因为vec没有定义大小是可变长度的,因此要用push_back来增加长度。

for(int i=0;i<1000;i++){//求交集
		if((vec1[i]!=0)&&(vec2[i]!=0)){//若vec1和vec2中有交集
			vec.push_back(i);//使用push_back函数增加vec长度
		}}

以上就是我使用数组作为hash表来解题的过程,若有uu不太明白的,可以私信我,我们一起讨论讨论。


(2)set解法

先上代码如下:

 vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
	unordered_set<int>st1;//使用unordered_set来存入nums的元素
	unordered_set<int>st2;
	unordered_set<int>result;//存放交集元素
	int len1=nums1.size();//得到两个nums的长度
	int len2=nums2.size();
	for(int i=0;i<len1;i++){//将nums元素存入set中
		st1.insert(nums1[i]);
	}
	for(int i=0;i<len2;i++){
		st2.insert(nums2[i]);
	}
	for(auto it:st2){//判断是否有交集元素,若有则存入result中
		if(st1.find(it)!=st1.end()){
			result.insert(it);
		}
	}
	return vector<int>(result.begin(),result.end());//返回vector类型
}

这里使用set或者是unordered_set的最大的区别和优点是,set是具有互异性的,意思就是任何元素不能在set中重复出现,而且set对于这种分散、稀疏的数组存放元素的时间复杂度比使用vector要小,而set与unordered_set的区别是,set的底层是使用的红黑树,而unordered_set的底层是使用的hash表,而且set中的元素是有序的,而unordered_set是无序的是按照存入的顺序存放的。同时set对比vector的区别有:第一、set不能按照下标访问元素,即不能出现set[i]这样的;第二、set不能直接存入元素,因为它都不能set[i]当然就不能直接按下标存入元素了,而要使用insert函数来插入元素。

使用set的思路与数组的思路差不多,但是在寻找交集元素的时候会方便一点,我同时讲讲这里的代码吧。

这里相当于使用的一个迭代器来遍历st2中的元素是否在st1里面,使用find函数来寻找,若find不等于尾迭代器,则说明在前面的迭代器中找到了该元素,说明该元素在st1中,说明是交集元素,存入result中即可。(for(auto it :st2)这种遍历是很方便的相当于重新定义,同时好像是只有c++11可以用auto吧,请各位uu自行去找找相关资料)。

for(auto it:st2){//判断是否有交集元素,若有则存入result中
		if(st1.find(it)!=st1.end()){//使用find函数,若不等于st1的尾迭代器,则说明在前面的迭代器中找到了该元素,就是该元素存在在st1中
			result.insert(it);
		}
	}

四、后记

进入hash表这部分,我觉得应该多去尝试使用set、map、pair这些不太熟悉的容器,这样其实对于提高算法能力有巨大的飞跃和帮助,可以简单的就解决一些以前复杂的问题。此外各位uu如果发现有不对的地方请私信我,大家一起讨论、学习,互相进步。我们都有光明的未来!!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值