代码随想录算法训练营day12 | 哈希表、字符串阶段性总结

做一下哈希表和字符串的阶段性总结,后面系统学完再进行修改补充。

哈希表

一般来说哈希表都是用来快速判断一个元素是否出现集合里。

什么时候使用哈希法?
当我们需要查询一个元素是否出现过,或者一个元素是否在集合里的时候,就要第一时间想到哈希法。

对于哈希表,要知道哈希函数和哈希碰撞在哈希表中的作用。

哈希函数是把传入的key映射到符号表的索引上。

哈希碰撞处理有多个key映射到相同索引上时的情景,处理碰撞的普遍方式是

  • 拉链法
  • 线性探测法

常见的三种哈希结构:

数组
set(集合)
map(映射)

在C++语言中,set 和 map 都分别提供了三种数据结构,每种数据结构的底层实现和用途都有所不同。

什么时候用std::set,什么时候用std::multiset,什么时候用std::unordered_set,都要思考。
注:
只有对这些数据结构的底层实现很熟悉,才能灵活使用,否则很容易写出效率低下的程序。

字符串

定义

字符串是若干字符组成的有限序列,也可以理解为是一个字符数组。每个语言对字符串都有不同的规定,我这里是针对C/C++中的字符串。

C语言

在C语言中,把一个字符串存入一个数组时,也把结束符 '\0’存入数组,并以此作为该字符串是否结束的标志。

char a[5] = "asd";
for (int i = 0; a[i] != '\0'; i++) {}

C++

在C++中,提供一个string类,string类会提供 size接口,可以用来判断string类字符串是否结束,就不用’\0’来判断是否结束。

string a = "asd";
for (int i = 0; i < a.size(); i++) {}

vector和string的区别

在基本操作上没有区别,但是 string提供更多的字符串处理的相关接口,例如string 重载了+,而vector却没有。

所以想处理字符串,我们还是会定义一个string类型。

是否使用库函数

在day08的344.反转字符串中刚开始联系字符串的时候,不能太依赖库函数,否则你会不了解诸如substr,split,reverse等库函数的实现原理和时间复杂度。
若在面试的时候面试官问让你分析时间复杂度的话,答不上来的话可能这个offer就没了。

所以,如果题目关键部分可以直接使用库函数来解决,建议还是不要使用库函数,
但如果仅仅是解题过程中的一小部分,且你很清楚这个库函数的实现原理,可以考虑使用库函数。

双指针法

在day01的27.移除元素和在day08的344.反转字符串,都使用的双指针法。
可以发现,双指针法在数组和链表和字符串中很常用。
在字符串:替换空格/元素,同样还是使用双指针法在时间复杂度O(n)的情况下完成替换空格/元素。

很多数组填充类的问题,都可以先预先给数组扩容带填充后的大小,然后在从后向前进行操作。

使用for循环里调用库函数erase来移除元素,这其实是O(n^2)的操作,因为erase就是O(n)的操作,所以这也是典型的不知道库函数的时间复杂度,而直接使用导致时间超时。

反转系列

在day08中541.反转字符串II 中,你可能会这样处理逻辑:每隔2k个字符的前k的字符,写了一堆逻辑代码或者再搞一个计数器,来统计2k,再统计前k个字符。
我当时也是这个写法,看了题解后才发现了更好的做法,
其实当需要固定规律一段一段去处理字符串的时候,要想想在for循环的表达式上做文章。

只要让 i += (2 * k),i 每次移动 2 * k 就可以了,然后判断是否需要有反转的区间。

因为要找的也就是每2 * k 区间的起点,这样写程序会高效很多。

在day08的151.翻转字符串里的单词里的单词中要求翻转字符串里的单词,是考察字符串的好题。

这道题目通过 先整体反转再局部反转,实现了反转字符串里的单词。

后来发现反转字符串还有一个好的用处,就是达到左旋的效果。

KMP

KMP的主要思想是当出现字符串不匹配时,可以知道一部分之前已经匹配的文本内容,可以利用这些信息避免从头再去做匹配。

KMP的精髓所在就是前缀表。

前缀表:起始位置到下标i之前(包括i)的子串中,有多大长度的相同前缀后缀。

那么使用KMP可以解决两类经典问题:

匹配问题:28. 实现 strStr()
重复子串问题:459.重复的子字符串
再一次强调了什么是前缀,什么是后缀,什么又是最长相等前后缀。

前缀:指不包含最后一个字符的所有以第一个字符开头的连续子串。

后缀:指不包含第一个字符的所有以最后一个字符结尾的连续子串。

然后针对前缀表到底要不要减一,这其实是不同KMP实现的方式,在day09分别给出了两个不同版本的的KMP实现。

其中主要理解j=next[x]这一步最为关键!

  • 24
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值