目录
描述:给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
1.暴力解法
O(),双指针遍历,直到找到两数之和等于target的,思路简单,但很及其低效。
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target){
for(int i=0;i<nums.size();i++){
for(int j =i+1;j<nums.size();j++){
if(nums[i]+nums[j]==target){
return {i,j}; //c++返回数组 return {a,b};
}
}
}
return {}; //返回函数返回types的对象,初始化为一个空的列表初始值设定项
}
};
学习:(return 知识)
- 返回数组 return {a,b,..}; 用大括号{},里面用,隔开
- return {} ; 返回函数要求类型的空值, 返回函数返回types的对象,初始化为一个空的列表初始值设定项
- return NULL; 返回值为NULL (C++中NULL与0等价),C++11的标准中加了一个用来表示空指针的常量值——nullptr;
- return ; 返回的是void,空值
- #ifdef 判断某个宏是否被定义,若已定义,执行随后的语句
- #ifndef 与#ifdef相反,判断某个宏是否未被定义
- __cplusplus cpp中的自定义宏,那么定义了这个宏的话表示这是一段cpp的代码
#ifndef NULL //如果没有宏定义NULL的话 #ifdef __cplusplus // 如果定义了__cplusplus宏(定义了就说明这是C++代码) #define NULL 0 // NULL的值就是0 #else #define NULL ((void *)0) //不是C++代码,定义NULL可以为空指针(为了兼容C) #endif #endif
暴力解法:执行用时: 488 ms,内存消耗: 9.6 MB
2.hash表
我们需要寻找两个数相加等于target,即对于一个给定的元素nums[i],在列表中找到另一个元素target-nums[i],找target-nums[i],用BF一一比较的话复杂度为O(n)
hashmap:但是如果用hashmap将数组所有值作为key(hash运算之后的值,比如modp运算...),数组下标为value,那么找我们找一个特定的值,只需要O(1)的复杂度。总的复杂度为O(n)
1.边赋值,边查找:
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int,int> hashtable; //建立一个空的hash表,key和value均为int型
for(int i=0;i<nums.size();i++){ //遍历
auto it=hashtable.find(target-nums[i]); //每次在所有值中查找新值
if(it!=hashtable.end()){ //找到,返回新值,及对应值的下标
return {it->second,i};
}
hashtable[nums[i]]=i; //没找到,就把新值加入hash表
}
return {};
}
};
执行用时: 8 ms内存消耗: 10.6 MB
学习:(hashmap知识)
- hash表:就相当于原来你在数组中找一个相应的数,需要每个对比,但是现在我把值都标上号(hash函数),然后顺着标号一下就找到了,但是需要空间开销
- 创建一个unordered_map的对象hashtable,key和value均为int型。
- 因为我们要找一个值:target-nums[i],判断这个数组值是不是存在,所以就以数组值作为hashtable的key,数组索引做value,来寻找。
- auto:定义iterator值,避免了写类型(unordered_map<int,int>::iterator it=...)使用auto定义变量时必须对其进行初始化,在编译阶段编译器需要根据初始化表达式来推导auto的实际类型。编译器在编译期会将auto替换为变量实际的类型。
- hashtable.find():如果找到,返回iterator值(hashtable中的元素值),如果没找到,返回hashtable.end(),也就是空的
- it->second:返回当前iterator值的value值,此处即索引值,i返回索引值(it->first返回key值)。
- 赋值操作hashtable[nums[i]]=i; 对hashtable进行赋值,每次赋值并对已有的进行寻找,如果存在必然可以找到
- 其实可以先全部赋值,在一一寻找
1.哈希表的高速查找是空间换时间的典型应用,前期的建立时间随着数量级的增加而增加,后期的查找则永远是O(1)。如果面对海量数据,且需要大量搜索,那建议使用哈希表。而当面对小量数据(数量级由服务器决定)时,使用List更合适。2.map与unordered_map:
map:key为有序排列,底层是红黑树,查找插入删除均为对数复杂度,。set同理。
unorderded_map:key为无序排列,底层实现为hash table,理想情况查找复杂度为常数,消耗内存较多。unordered_set同理。3.返回值类型是vector<int>,也是一个迭代器,数组值,根据代码可知,hashtable返回值需要加{},{}为空,返回一个数组,就直接在{}里面写多个值即可
2021-06-08
hashmap:查找时间复杂度O(1),yyds!就相当于找一本书,我把书的名字结果hash运算,给变成了一串对应的数字key——相当于编号了,然后找那本书直接找那个编号就行了,把值hash成了key,直接找索引就行了,其实也是一种简化思想。
将具象的东西给简化、抽象化,将其与一个个容易查找的东西对应起来(编号key值),然后理顺了就好找了