最近,出于巩固复习C++与数据结构、学习高级算法、准备PAT考试的需要,我开始照着网上的刷题教程,在力扣和PAT平台上逐题攻坚。以下是一些收获:

【1】map容器的使用

  1. make_pair返回pair对象,可以作为map容器的元素insert如下:

    map.insert(make_pair(键,值));
  2. map的键值对访问:map[键]=值。其中,键为const修饰
  3. map的迭代器访问:
    for(map<type1,type2>::iterator it=m.begin;it!=m.end();it++)
    {//对键进行操作(数值类型的键默认从小到大排序)it->first...//对值进行操作it->second...
    }
  4. map.find返回迭代器,搜不到时返回map.end()
  5. map.count(键)返回int值,搜不到时返回0
  6. 删除键值对:map.erase(it)

【2】iterator容器的使用

  1. 1.迭代器基础语法

    1. 定义+初始化(以vector<int>为例):

      vector<int>::iterator it=v.begin();
    2. 取值:*it或it->
    3. 迭代:it++(单向迭代器,即iterator,不支持++外的数值操作符,包括--)
    4. 迭代器化为下标:std::distance(it1,it2)
  2. 迭代中删除元素
    1. 格式:it=it.erase(element)
    2. erase的返回值为下一个元素(注意,“下一个”被定义为从begin到end的下一个)
    3. 因此,it++不应该写在for里,避免删除后发生2次迭代
  3. 反向迭代器

定义+初始化+迭代(以vector<int>为例):

for(vector<int>::reverse_iterator it=v.rbegin();it!=v.rend();it++)

【3】sort的使用

  1. STL容器:

    sort(stlType.begin(),stlType.end());//以默认方式对stlType容器内的元素排序
  2. 函数对象(以lambda表达式为例,也可以自定义cmp函数并传入sort中执行):
sort(stlType.begin(),stlType.end(),[需要引用的外部变量](参数)->返回值
{函数体
});
//反向排序vector<int> v
sort(v.begin(),v.end(),[](int x,int y)->bool
{return x>y;
});

【4】二分法的巩固学习

长期以来,我对二分法报有抽象而不具体的认识,只会用binary_search、lower_bound和upperbound接口。经过分析和讨论,我认为二分法的具体实现其实并无模板可记,但有清晰的规则可考。

  1. 二分法的写法由以下因素决定:

    1. 开闭区间选择
    2. 目标条件
    3. 是否需要对重复元素求边界
  2. 二分法的写法由以下部分组成:
    1. 初始区间
    2. 终止条件
    3. 区间缩小条件(arr[m]==num之类的)
    4. 区间缩小语句(l=m,r=m-1之类的)
    5. 返回值
  3. 对各个细节的归纳:
    1. 目标条件和有无重复如何影响二分法: 二分法的直接产物是特定的数值,至于>=、<=、<、>均为间接产物。也就是说,是目标条件的端点而非范围,参与决定了二分法的写法。注:针对有重数组的二分法可以得到特定数值的上下边界。详情见5
    2. 关于初始区间和终止条件的归纳: 全闭区间[0,arrSize-1],l<=r;左闭右开区间[0,arrSize),l<r。注:这两种我比较常用,其它的写法其实都可以,但是要能够熟练而且正确地写出。
    3. 关于区间缩小条件的归纳: 由1知,根据目标条件中隐含的端点即可。需要注意的是有重数组,详情见5
    4. 关于区间缩小语句的归纳:
      1. 全闭区间直接用+1、-1。
      2. 半开区间或全开区间,在开的半边“隐式缩小”区间即可。对于[l,r),即令l=m+1或r=m。
    5. 关于返回值的归纳:
      1. 无重复数组: 左闭右闭,返回m;左闭右开,返回l
      2. 有重复数组: 返回pos。pos的取值:下边界,则在>=时取m;上边界,则<=时取m。如此,pos会随着m改变而改变。实现见下述代码段
        //针对有重数组arr,求小于0的最右侧元素下标
        int test0(int* arr,int arrSize)
        {//左闭右闭 int l=0,r=arrSize-1;int pos;while(l<=r){ int m=l+((r-l)>>1);//此处的写法应该记忆,2点好处不言自明//细节:这样的m始终取较小的值 if(arr[m]<0){l=m+1;}else{r=m-1;pos=m;}   }return pos;
        }

【5】自动机实现的KMP算法

(两者都是我很早就感兴趣的知识点,但一直懒得看,最近学了一下。可能实用性不高)

  1. 名词解释

    1. 模式pattern: 如AAAB
    2. 文本text: 如AAACAAAB/AAAAAAAB
    3. 需求:在text里找pattern,而且不用暴力法,要求在遍历pattern的时候“聪明点”
    4. 状态: pattern在使用中由一个字符转换到一个字符(不一定是前一个字符转换到后一个字符),则前后为各为一个状态;
    5. 状态推进: text的下一个字符仍然匹配pattern的下一个字符,由前一个字符转换到后一个字符;
    6. 状态回退: 下一个字符不匹配,若可以匹配影子状态,则在pattern中发生有限的回退。否则,发生完整回退;
    7. 影子状态: 最长的相同前缀位置。比如,在pattern字符串ABABC中,第二个A的影子是第一个A,第二个B的影子是第1个B,C没有影子。
    8. 转移过程: 根据text的下一个字符,转移到pattern的哪个位置,整个过程由二维数组dfa记录;
    9. dfa:自动机。其实就是记录(状态,情况)映射至(新状态)的数组。
      1. dfa[状态][text的下一个字符]
      2. =下一个状态
      3. ={pattern下一个字符
      4. {dfa[最近的影子状态位置][text的下一个字符]
    10. (值得记录的细节)dfa[patternSize][charSetSize]对应关系:0~null 1~pattern[0] ... patternSize-1~pattern[patternSize-2]
  2. 例图与原博客

    https://pic3.zhimg.com/v2-2788562d1059d7b8ff71aa342e4ae036_r.jpgKMP 算法详解 - 知乎 (zhihu.com)

  3. 构建dfa数组的具体实现

    1. 双层循环的含义:外层i表示pattern的各个位置,内层j表示(状态,各个可能的字符)对应的状态转移

    2. 重要变量x(记录下一个位置的影子状态,规则也是推进和回退):在外层循环中更新,x=dfa[x][pattern[i]],即pattern[i+1]的影子状态=pattern[i]的影子状态遇到字符pattern[i+1]的转移后状态。x初始化为0,因为pattern[0]、dfa[1]的影子状态一定为null

    3. 内层循环:推进和回退

#include<iostream>
using namespace std;class DFA_KMP
{
public:string pattern;int patternSize;int charSetSize;int** dfa;DFA_KMP(string pattern,int charSetSize){this->pattern=pattern;this->patternSize=pattern.size();this->charSetSize=charSetSize;dfa=new int*[patternSize];for(int i=0;i!=patternSize;i++){dfa[i]=new int[charSetSize];}}void dfaBuilder(){   //i:0-a,1-b,2-a,3-b,4-c//j:0-a,1-b,2-c //dfa[0][]为"ababc"之前的空位的状态转移数组 for(int i=0;i!=charSetSize;i++){if(i!=pattern[0]-97)dfa[0][i]=0;else dfa[0][i]=1;}//影子状态位置 int x=0;for(int i=1;i!=patternSize;i++){for(int j=0;j!=charSetSize;j++){//状态推进 if(pattern[i]-97==j)dfa[i][j]=i+1;//状态回退 else dfa[i][j]=dfa[x][j];}//更新影子状态位置x=dfa[x][pattern[i]-97];//cout<<x<<'\n';}}int matcher(string text){int textSize=text.length();int j=0;for(int i=0;i!=textSize;i++){j=dfa[j][text[i]-97];if(j==patternSize)return i-patternSize+1;}return -1;}
};int main()
{//只有a/b/c三个字母尝试进行KMP匹配,便于debug DFA_KMP algOb("ababc",3);algOb.dfaBuilder();cout<<"构建状态转移数组\n";for(int i=0;i!=algOb.patternSize;i++){for(int j=0;j!=algOb.charSetSize;j++){cout<<algOb.dfa[i][j]<<' ';}cout<<'\n';}cout<<"在text字符串下标为"<<algOb.matcher("abababc")<<"处发现模式字符串"<<'\n';//任务://学会构造dfa数组 //学会更新影子状态 //完成完整的KMP return 0;
}

C++刷力扣、PAT第一周笔记相关推荐

  1. 零基础的我刷力扣一周后,总结了点东西

    一.前言 之前一直想学习数据结构与算法,因为一直听说这个很重要嘛,还有力扣这个网站那也是神交已久啊~~ 但是又不敢接触,因为恐惧嘛,害怕学不会,害怕被吊打~~~~~ 后来遇到了一个大佬,算法大佬,超强 ...

  2. 【关于为什么要刷力扣的思考】记第二次周赛AK

    前言 从上次AK周赛的一月底,磕磕绊绊到五月初,总共经历了20多场的周赛 在这20场周赛中,四题:三题:两题:一题 = 2:12:8:1 总体来说应该还是在两到三题中间徘徊 但很多时候做出的两题,并非 ...

  3. 20210627:力扣第247周周赛(上)

    力扣第247周周赛(上) 题目 思路与算法 代码实现 写在最后 题目 两个数对之间的最大乘积差 循环轮转矩阵 思路与算法 两个数对之间的最大乘积差:排序相减即可 循环轮转矩阵:模拟即可,注意逆时针和顺 ...

  4. 20210601:力扣第243周周赛(上)

    力扣第243周周赛(上) 题目 思路与算法 代码实现 写在最后 题目 检查某单词是否等于两单词之和 插入后的最大值 思路与算法 检查某单词是否等于两单词之和:直接转化比较即可 插入后的最大值:负数,则 ...

  5. 20210426:力扣第238周周赛(上)

    力扣第238周周赛(上) 题目 思路与算法 代码实现 写在最后 题目 K 进制表示下的各位数字总和 最高频元素的频数 思路与算法 第一题是数学题,考察各进制与十进制数的相互转换,不多赘述,连续取余求和 ...

  6. 20210424:力扣第237周周赛(下)

    力扣第237周周赛(下) 题目 思路与算法 代码实现 写在最后 题目 单线程 CPU 所有数对按位与结果的异或和 思路与算法 第一题属于一类cpu流水线题目,实现常规方法堆加排序即可. 第二题属于数学 ...

  7. 20210217:力扣第228周周赛(上)

    力扣第228周周赛(上) 题目 思路与算法 代码实现 写在最后 题目 生成交替二进制字符串的最少操作数 统计同构子字符串的数目 思路与算法 第一题需要注意不能直接翻译题意,直接翻译的代码存在先入为主定 ...

  8. 20210201:力扣第226周周赛(上)

    力扣第226周周赛(上) 题目 思路与算法 代码实现 写在最后 题目 盒子中小球的最大数量 2. 1743. 从相邻元素对还原数组 思路与算法 第一题简单的数数问题,python比较方便,使用str函 ...

  9. 20200727:力扣第31周双周赛题解

    力扣第31周双周赛题解 题目一:在区间范围内统计奇数数目 给你两个非负整数low和high,请你返回low和high之间(包含二者)奇数的数目 0 <= low <= high <= ...

最新文章

  1. snp可视化之瀑布图
  2. php 插入 mysql_php插入mysql数据返回id的方法
  3. 联想一体机电源键不亮_联想/兄弟打印机复印一体机激光器清洁教程
  4. Wrapper+map实现页面显示
  5. 题解 P1091 【合唱队形】
  6. 分子排列不同会导致_武汉理工《Matter》:构筑晶体内跨尺度分子筛单晶反应器...
  7. 二、Spring Cloud的配置 之 Eureka(服务注册中心)配置
  8. 个图标当十个用—多功能系统级图标制作攻略
  9. Java - 批量生成二维码压缩包
  10. elasticsearch中forcemerge清除文件占用的磁盘空间
  11. 删库跑路技巧 删库跑路命令
  12. WIN7 声音图标不见
  13. 中望3D 2021 自动缩放基准面大小
  14. 2.3.2 合并(拼接)字符串
  15. python中科学记数法表示_matplotlib中的科学记数法
  16. 线代9讲_特征值与特征向量相似理论
  17. 公众号h5获取手机号权限_微信公众号开发之网页授权(获取用户信息)
  18. ESP32 开发笔记(四)littleVGL LVGL 控件学习 Arc 弧形控件
  19. 笔记 - JavaScript - 超哥视频
  20. 编码 人的语言与机器语言转换

热门文章

  1. 管理者的五大能力十大素质
  2. 【刷题】阿里20200330笔试
  3. 如图,甲乙两人分别在AB两地同时相向而行,于E处相遇后,甲继续向B地行走,乙则休息了14分钟,在继续向A地行走,甲和乙到达B和A后立即折返,又在E处相遇,已知甲每分钟行走60米,乙每分钟行走80米
  4. 「技术趋势」软件开发人员应该了解的2021年技术趋势
  5. 第6天2021-08-13
  6. IT 大牛们的小传,有点academic风格的说^_^
  7. 教师资格证面试试讲时可以戴手表吗
  8. 一般UI设计要学习的内容都有哪些
  9. 马云成全球50大领袖人物排名第二,凭什么?
  10. 服务器获取真实客户端 IP