数组和字符串常用技巧和知识点

数组和字符串常用技巧和知识点,第1张

数组和字符串常用技巧和知识点 数组 和 字符串

注:博客内容只限于个人学习。图片和内容可能整合了多渠道的信息来源,如侵联系可删。

归并排序 分治思想

分: 不断将数组从中点位置划分开(即二分法),将整个数组的排序问题转化为子数组的排序问题;
治: 划分到子数组长度为 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++上下取整数

#include  double 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排序
#include
using 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 对象支持互相直接赋值

未完待续…

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5520762.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-13
下一篇 2022-12-13

发表评论

登录后才能评论

评论列表(0条)

保存