0 unordered_map
- map与unordered_map
- map: map内部实现了一个红黑树,红黑树具有自动排序的功能,因此map内部的所有元素都是有序的
- unordered_map: 内部实现了一个哈希表。其元素的排列顺序是无序的
- map:
优点:有序性
缺点: 空间占用率高,因为map内部实现了红黑树,虽然提高了运行效率,但是因为每一个节点都需要额外保存父节点、孩子节点和红/黑性质,使得每一个节点都占用大量的空间
适用处:对于那些有顺序要求的问题,用map会更高效一些 - unordered_map:
优点: 因为内部实现了哈希表,因此其查找速度非常的快
缺点: 哈希表的建立比较耗费时间
适用处:对于查找问题,unordered_map会更加高效一些,因此遇到查找问题,常会考虑一下用unordered_map
- 定义:
unordered_set<int>s;
和unordered_map<string ,int>s;
- 查找元素:
查找x是否在map中
方法1: 若存在 if(mp.find(x)!=mp.end())
方法2: 若存在 if(mp.count(x))
- 插入元素x:
mp.insert(x)
iterator->second
对于map
it->first
会得到key,it->second
会得到value。
1最大子序和
/类似寻找最大最小值的题目,初始值一定要定义成理论上的最小最大值 INT_MIN
和INT_MAX
2两数之和
return{}
表示返回一个空的vector 。return{1,2}
表示返回一个vector:[1,2]
3合并两个有序数组
i++ 是先引用后增加 ,先在i所在的表达式中使用i的当前值,后让i加1
++i 是先增加后引用,让i先加1,然后在i所在的表达式中使用i的新值
思路1:反向双指针
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int i = n + m - 1;
int p1 = m -1;
int p2 = n - 1;
while (p1 >= 0 and p2 >= 0) {
if (nums1[p1] < nums2[p2]) nums1[i--]= nums2[p2--];
else {
nums1[i--] = nums1[p1--];
}
}
while (p1 >= 0) nums1[i--] = nums1[p1--];
while (p2 >= 0) nums1[i--] = nums2[p2--];
}
4 两个数组的交集 II
统计nums1中每个元素出现的次数
unordered_map <int, int> m;
for (int num : nums1) {
++m[num]; //
}
5 杨辉三角
6 重塑数组
获取二维数组v的行和列:
-
int row = v.size();
-
int col =v[0].size();
思路:对于m×n的矩阵V1转换为r*c的矩阵V2,
7合并两个数组
方法一:insert
vector<string>vec1,vec2,vec3;
//... vec1,vec2赋值
vec3.insert(vec3.end(),vec1.begin(),vec1.end());
vec3.insert(vec3.end(),vec2.begin(),vec2.end());
方法二:merge()
[注]:
- 合并后的数组需要提前指定好大小
- 合并的两个数组必须有序
vector<string>vec1,vec2,vec3;
//... vec1,vec2赋值
sort(vec1.begin(),vec1.end());
sort(vec2.begin(),vec2.end());
vec3.resize(vec1.size()+vec2.size());
merge(vec1.begin(),vec1.end(),vec2.begin(),vec2.end(),vec3.begin());
1二分查找
前提:数组为有序数组,同时题目还强调数组中无重复元素
[l,r] : while (left <= right) r = mid - 1
[l,r) while (left < right) r = mid;
int search(vector<int>& nums, int target) {
int l = 0, r = nums.size() - 1;
while (l <= r) {
int mid = ((r - l) >> 1) + l;
if (nums[mid] == target) return mid;
else if (nums[mid] > target) r = mid - 1;
else {
l = mid + 1;
}
}
return -1;
}
2 二分查找-II
有重复数字的升序数组的二分查找,返回出现targer的第一个数组下标
找到target后,只要mid>=0且nums[mid - 1]也等于target,就mid–,直至找到第一个。
int search(vector<int>& nums, int target) {
// write code here
int l = 0, r = nums.size() - 1;
while (l <= r) {
int mid = ((r - l) >> 1) + l;
if (nums[mid] == target) {
while (mid != 0 and nums[mid - 1] == target) mid--;
return mid;
}
else if (nums[mid] > target) r = mid - 1;
else {
l = mid + 1;
}
}
return -1;
}
3 求平方根
满足有序和无重复元素
除0以外,所有非负整数的平方根都在1-它本身之间
因为取整,所以取整后的平方根res,res²<x, (res+1)² >x
- 因此左边界l=1,右边界r= x。边界条件l<= r,能取等号的原因:例如l=1=x,也可以进行下面的操作。
- 求出中间值,若中间值的平方>x,说明中间值大了,此时应该缩小右边界r = mid - 1;
- 中间值的平方<x,且中间值+1的平方>x,则说明就是所求的平方根,否则说明中间值小了,应该增大左边界l=mid+1;
int mySqrt(int x) {
int l = 1, r = x;
while (l <= r) {
int mid =((r - l) >> 1) + l;
if (mid > x / mid) {
r = mid - 1;
}
else {
if (mid + 1 > x / (mid + 1)) return mid;
l = mid + 1;
}
}
return 0;
}
位运算
1 左移运算符<<
:左移第一个操作数的位,第二个操作数确定要移位的位数。或者换句话说,将整数“ x”与整数“ y”(x << y)左移等效于将x乘以2 ^ y(2乘幂y)。
2 右移运算符>>
:取两个数字,右移第一个操作数的位,第二个操作数决定移位的位数。类似地,右移(x >> y)等于将x除以2 ^ y。
3 异或运算 ^
和 xor
:
0^0=0; 0^1=1; 1^0=1; 1^1=0;
性质:
a.满足交换律
b 两个一样的数异或结果为0
c 0 xor n = n
4