注:博客内容只限于个人学习。图片和内容可能整合了多渠道的信息来源,如侵联系可删。
归并排序 分治思想
分: 不断将数组从中点位置划分开(即二分法),将整个数组的排序问题转化为子数组的排序问题;
治: 划分到子数组长度为 1 时,开始向上合并,不断将 较短排序数组 合并为 较长排序数组,直至合并至原数组时完成排序;
参考
https://leetcode-cn.com/problems/shu-zu-zhong-de-ni-xu-dui-lcof/solution/jian-zhi-offer-51-shu-zu-zhong-de-ni-xu-pvn2h/
class Solution { public: int reversePairs(vector& nums) { vector tmp(nums.size()); return mergeSort(0, nums.size() - 1, nums, tmp); } private: int mergeSort(int l, int r, vector & nums, vector & tmp) { // 终止条件 if (l >= r) return 0; // 递归划分 int m = l + (r-l)>> 2; int res = mergeSort(l, m, nums, tmp) + mergeSort(m + 1, r, nums, tmp); // 合并阶段 int i = l, j = m + 1; for (int k = l; k <= r; k++) tmp[k] = nums[k]; for (int k = l; k <= r; k++) {//填补tmp数组对应位置 if (i == m + 1) nums[k] = tmp[j++]; else if (j == r + 1 || tmp[i] <= tmp[j]) nums[k] = tmp[i++]; else { nums[k] = tmp[j++]; res += m - i + 1; // 统计逆序对 } } return res; } };
数组题常见套路
1.双指针:双指针灵活擦 *** 作,可以起到降低一个等级复杂度的作用
2.滑动窗口:重要性质是窗口的左边界和右边界永远只能向右移动,而不能向左移动。这是为了保证滑动窗口的时间复杂度是 O(n)。如果左右边界向左移动的话,这叫做“回溯”,算法的时间复杂度就可能不止 O(n)。(又可以分为固定窗口,可变窗口)
在滑动窗口类型的问题中都会有两个指针,一个用于「延伸」现有窗口的 r 指针,和一个用于「收缩」窗口的 l 指针。在任意时刻,只有一个指针运动,而另一个保持静止
3.根据数组中数据 *** 作的需求可以选取适当数据结构,如栈,堆,队列等
需要保留和丢弃相邻的元素:栈
//c++上下取整数 #includedouble floor(double x ); float floorf(float x); long double floorl(long double x); double floor(double x);S double ceil(double x); 使用floor函数。floor(x)返回的是小于或等于x的最大整数。 如: floor(10.5) == 10 floor(-10.5) == -11 使用ceil函数。ceil(x)返回的是大于x的最小整数。 如: ceil(10.5) == 11 ceil(-10.5) ==-10 floor()是向负无穷大舍入,floor(-10.5) == -11; ceil()是向正无穷大舍入,ceil(-10.5) == -10
滑动窗口例题:
209. 长度最小的子数组
904. 水果成篮 76. 最小覆盖子串滑动窗口总结:https://mp.weixin.qq.com/s?__biz=MzAxODQxMDM0Mw==&mid=2247485141&idx=1&sn=0e4583ad935e76e9a3f6793792e60734&scene=21#wechat_redirect
C++ STL中Map的按Value排序#includeusing namespace std; typedef pair PAIR; bool cmp_by_value(const PAIR& l, const PAIR& r) { return l.second < r.second; } int main() { map name_score_map; name_score_map["LiMin"] = 90; name_score_map["ZiLinMi"] = 79; name_score_map["BoB"] = 92; name_score_map.insert(make_pair("BoB",99));//不会插入或者更新 name_score_map.insert(make_pair("Albert",86)); //把map中元素转存到vector中,以pair的形式 vector name_score_vec(name_score_map.begin(), name_score_map.end()); sort(name_score_vec.begin(), name_score_vec.end(), cmp_by_value); for (auto iter: name_score_vec) {//这里的ater不是迭代器,是指代元素,要注意 cout << iter.first << endl;//注意:pair不能以元素遍历形式取出,只能以.first或者.second取key或者value。(map迭代器则用->,如下) // for (auto iter=name_score_map.begin();iter!=name_score_map.end();iter++) { // cout << iter->second<< endl; } return 0; } //技巧:也可以把key和value颠倒组成pair,然后存进vector,这样不用写cmp
map set pair 好题:(2034. 股票价格波动)
收获:
-
map赋值的两种方式:map[key]=value ,如果已经有该key,会覆盖原始值 ,map.insert(pair
(2,4))形式则不会插入也不会修改 -
灵活处理map,set和pair。核心:pair数据类型,map和set是容器,且这两个容器都会自动排序(map根据key。set如果存的是pair类型,则会根具pair第一个元素)
-
//map的erase()可以这样写: auto iter = m.find(1);//找到要删除的迭代器 if(iter!=m.end()) m.erase(iter); //set的erase(),括号中是set中的元素
-
//set常用 *** 作: 除了insert(),erase(),size(),empty()常用: rbegin():返回指向最后一个(注意,是已排好序的最后一个)元素的迭代器 find(val):在set容器中查找值为val的元素,如果成功找到,则返回指向该元素的双向迭代器;反之,则返回和end() 方法一样的迭代器 count(val) 在当前 set 容器中,查找值为 val 的元素的个数,并返回。注意,由于 set 容器中各元素的值是唯一的,因此该函数的返回值最大为 1
-
set,map和vector容器互相转换的问题: //vector和set可以自由转换 vec = { 1, 2, 3, 4, 8, 9, 3, 2, 1, 0, 4, 8 }; set
st(vec.begin(), vec.begin()+3);两者互相截取迭代器区间即可 //vector和map转换 map.insert(pair (1,2));//pair类型赋值 vector > vec(map.begin(),map.end());//map类型转进vec,类型为pair
字符串拼接可以直接用‘+’
//substr用法 #include#include using namespace std; int main() { string s("12345asdf"); string a = s.substr(0,5); //获得字符串s中从第0位开始的长度为5的字符串 cout << a << endl; //substr越界问题: https://blog.csdn.net/saiolive/article/details/53102298?spm=1001.2101.3001.6650.2&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-2.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-2.no_search_link
string 对象支持互相直接赋值
未完待续…
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)