“ 多做善事才是好运的根本!”
2018年9月14日
8月、9月、10月~
挺过去,一切都会好的,
但是竭尽全力,
因为,你后悔不起~
记录下C++、数据结构中的一些知识用法吧:
我们都知道,容器是存放数据的地方,常见的容器有序列式容器和关联式容器,序列式容器,即其中的元素不一定有序,但可以被排序,比如vector、list、queue、stack、heap、priority_queue;而关联式容器内部结构基本上是一个平衡二叉树。所谓关联,指每个元素都有一个键值和一个实值<key,value>,元素按照一定的规则存放。比如RB-tree、set、map、unordered_map、hashtable、hash_map、hash_set。
接下来着重介绍map和unordered_map:(用的最多)
map: #include <map>
unordered_map: #include <unordered_map>
算了,说一下map和set的区别吧,set:其内部元素会根据元素的键值自动被排序;区别于map,它的键值就是实值,而map可以同时拥有不同的键值和实值。
map:
一对一的方式来存储数据,<关键字,映射值>,其内部通过R-B tree(红黑树)实现,而且会根据key值来自动将数据排序,因此map内部的所有元素都是有序的,红黑树的每一个节点都代表着map的一个元素。因此,对于map进行的查找,删除,添加等一系列的操作都相当于是对红黑树进行的操作。另外,map比hash_map(未进入stl)稳定,但是一般没有hash_map快。其时间复杂度:O(log n)
unordered_map:
unordered_map底层用一个哈希表(也叫散列表,通过把关键码值映射到Hash表中一个位置来访问记录,查找的时间复杂度可达到O(1),其在海量数据处理中有着广泛应用)来实现。因此,其元素的排列顺序是无序的。时间复杂度:O(1)常数级
明确下各自的优缺点:
map:
- 优点:
- 有序性,这是map结构最大的优点,其元素的有序性在很多应用中都会简化很多的操作
- 红黑树,内部实现一个红黑书使得map的很多操作在
lgn
的时间复杂度下就可以实现,因此效率非常的高
-
缺点: 空间占用率高,因为map内部实现了红黑树,虽然提高了运行效率,但是因为每一个节点都需要额外保存父节点、孩子节点和红/黑性质,使得每一个节点都占用大量的空间
-
适用处:对于那些有顺序要求的问题,用map会更高效一些
unordered_map:
- 优点: 因为内部实现了哈希表,因此其查找速度非常的快
- 缺点: 哈希表的建立比较耗费时间
- 适用处:对于查找问题,
unordered_map
会更加高效一些,因此遇到查找问题,常会考虑一下用unordered_map
举例:(包括map的声明、建立、遍历)
leetcode 1两数之和
/*
题目:leetcode 1 Two Sum 两数之和
从给定的一组数中找到两个数的和为target.返回两个数的序号,假设每次输入只有一组解
时间:2018年9月14日 12:16:34
思路:1.暴力搜索,对于每个数去找后面和它的和为target的数,如果找到了就返回,时间复杂度O(n^2)
2.hash:先进行hash映射,<key,value>为 <nums[i], i>,对于每一个数,可以在O(1)的时间找到
即:用空间来弥补时间,建立使用一个HashMap,来建立数字和其下标位置之间的映射,也就是我求得一个数就直接能知道它的下标。
我们都知道HashMap是常数级的查找效率,这样,我们在遍历数组的时候,用target减去遍历到的数字,就是另一个需要的数字了,
直接在HashMap中查找其是否存在即可,注意要判断查找到的数字不是第一个数字,比如target是4,遍历到了一个2,那么另外一个2不能是之前那个2,
整个实现步骤为:先遍历一遍数组,建立HashMap映射,然后再遍历一遍,开始查找,找到则记录index。
*/
#include <bits/stdc++.h>
using namespace std;
//法一:暴力搜索
class Solution {
public:
vector<int> twoSum(vector<int> &num, int target) {
vector<int> v;
for(int i=0;i<num.size();++i)
{
for(int j=i+1;j<num.size();++j)
{
if(num[i]+num[j]==target)
{
v.push_back(i);
v.push_back(j);
break;
}
}
}
return v;
}
};
//法二:hash表
class Solution {
public:
vector<int> twoSum(vector<int> &num, int target) {
vector<int> v;
unordered_map<int,int> m;//声明hash图
for(int i=0;i<num.size();++i)//建立hash图
{
m[num[i]]=i;
}
for(auto &it:m)//遍历hash图;
cout<<it.first<<" "<<it.second<<endl;
for(int i=0;i<num.size();++i)
{
int t=target-num[i];
if(m.count(t)&& m[t]!=i)//if(m.find(t)!=m.end()&&m[t]!=i)
{
v.push_back(i);
v.push_back(m[t]);
break;
}
}
return v;
}
};
int main()
{
vector<int> a={1,6,4,5,7};
Solution so;
vector<int> res;
res=so.twoSum(a,9);
for(auto i:res)//遍历容器的简单方法
cout<<i<<" ";
return 0;
}
一定要看懂,理解!
里面的写法很值得铭记。
最后,祝福所有努力的人,都会有好运!