今天开始在LeetCode刷题,第一题为“两数之和(Two Sum)”,整体来讲这一题难度是比较低的,但还是在这个过程中遇到一些问题,以下主要记录出现的一些问题。
这个题目比较容易想到的方法便是穷举了,很暴力但也很直接,需要注意的一点便是向量库Vector,自己也是前一阵子开始学数据结构才知道有这个库(有的也称为容器),定义计算数组长度用的方法是size()而不是length(),官方解答给的是length(),不知道是不是没有注意到还是因为他用的代码是Java(本人不了解Java),其余不再多说。
穷举也是我能想到唯一的方法了-_-||。。。因此看了官方题解,才知道还有哈希表这个好东西,其基本原理我就摘用网上的原话了:使用一个下标范围比较大的数组来存储元素。可以设计一个函数(哈希函数,也叫做散列函数),使得每个元素的关键字都与一个函数值(即数组下标,hash值)相对应,于是用这个数组单元来存储这个元素;也可以简单的理解为,按照关键字为每一个元素“分类”,然后将这个元素存储在相应“类”所对应的地方,称为桶。但是,不能够保证每个元素的关键字与函数值是一一对应的,因此极有可能出现对于不同的元素,却计算出了相同的函数值,这样就产生了“冲突”,换句话说,就是把不同的元素分在了相同的“类”之中。 总的来说,“直接定址”与“解决冲突”是哈希表的两大特点。 (--------------------- 原理这段话来自 剑西楼 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/q_l_s/article/details/52416583?utm_source=copy)
哈希表是一个在时间和空间上做出权衡的经典例子。如果没有内存限制,那么可以直接将键作为数组的索引。那么所有的查找时间复杂度为O(1);如果没有时间限制,那么我们可以使用无序数组并进行顺序查找,这样只需要很少的内存。哈希表使用了适度的时间和空间来在这两个极端之间找到了平衡。只需要调整哈希函数算法即可在时间和空间上做出取舍。( --------------------- 例子这段话来自 sam5828 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/mmmmcc/article/details/52885030?utm_source=copy)。
在网上查看了一些资料以后觉得哈希表与字典类似,都是利用键值对来存储数据,那么了解原理后学习hash_map的各种方法,上手!首先按照“两遍哈希表”的思路码代码,根据编译结果提示对代码进行不断地改写,最终还是没有成功,费了好大功夫最终在Visual Studio帮助文档中看到hash_map已经是个过去式了(心中一万头可爱的羊驼奔过...),现在用unordered_map替代,于是最终我选用了map类,当时并没有搞清楚两个具体有什么区别,只是大致了解了一下他们两个的方法几乎都是一样的,需要注意at方法和find方法的区别,前者返回键对应的值,后者返回引用映射当中具有与指定键等效的键的元素的位置的迭代器。完成两遍哈希表以后一遍哈希表也就顺其自然完成了。
三种方法的比较:
穷举法 | 两遍哈希表 | 一遍哈希表 | |
时间复杂度 | O(n2) | O(n)[哈希表查找元素时间为O(1),建表时间为O(n) | O(n) |
空间复杂度 | O(1) | O(n)[哈希表创建的额外空间取决于元素数量] | O(n) |
C++代码贴下方:
1 //穷举法 2 class Solution { 3 public: 4 vector<int> twoSum(vector<int>& nums, int target) { 5 for (int i = 0; i < nums.size(); i++) 6 { 7 for (int j = i + 1; j < nums.size(); j++) 8 { 9 if (nums[j] == target - nums[i]) 10 { 11 return {i, j}; 12 } 13 } 14 } 15 } 16 }; 17 18 //两遍哈希表 19 class Solution { 20 public: 21 vector<int> twoSum(vector<int>& nums, int target) { 22 map<int, int> tmap; 23 for(int i = 0; i < nums.size(); i++) 24 tmap.insert(make_pair(nums[i], i)); 25 for(int i = 0; i < nums.size(); i++) 26 { 27 int j = target - nums[i]; 28 if(tmap.count(j) == 1 && tmap.at(j) != i) 29 return {i, tmap.at(j)}; 30 } 31 printf("There is no two sum solution."); 32 } 33 }; 34 35 //一遍哈希表 36 class Solution { 37 public: 38 vector<int> twoSum(vector<int>& nums, int target) { 39 unordered_map<int, int> tmap; 40 for(int i = 0; i < nums.size(); i++) 41 { 42 tmap.insert(make_pair(nums[i], i)); 43 int j = target - nums[i]; 44 if(tmap.count(j) == 1 && tmap.at(j) != i) 45 return {tmap.at(j), i}; //注意此处找到符合条件元素时,tmap.at(j)的位置必然在i前方,因此输出时顺序颠倒 46 47 } 48 printf("There is no two sum solution."); 49 } 50 };
原文地址:https://www.cnblogs.com/LDTSB-0101001/p/9748398.html