字符串是若干字符组成的有限序列,也可以理解位是一个字符数组,但是很多语言对字符串做了特殊的规定。
在C语言中,把一个字符串存入一个数组时,也把结束符'\0'存入了数组,并以此作为该字符串是否结束的标志。
在C++中,提供了一个string类,string类会提供size接口,可以用来判断string类字符串是否结束,就不需要用'\0'来判断是否结束
有些同学有疑问vector<char>和string有什么区别呢
其实在基本操作上没有什么区别,但是string提供更多的字符串主力的相关接口,例如string重载了+,而vector却没有。所以说,我们要处理字符串,我们还是会定义一个string类型。
因为字符串中可以使用的库函数较多,所以很多同学习惯于调用substr(从一个字符串中提取指定位置和长度的子字符串)、split(将字符串分隔成包含子字符串的数组)、reverse(反转字符串)等库函数,我们当然可以使用,但是需要知道其具体如何实现,以及时间复杂度,否则,假设之后的面试中被问到如何实现又或者其时间复杂度是多少,就懵逼了。
所以建议,一道题目的关键部分可以直接用库函数解决,那么尽量自己动手写,而不是依靠库函数。如果库函数仅仅是解题过程中的一小部分,而且已经很清楚库函数的内部实现原理,可以考虑使用库函数。
单纯的字符串反转较容易理解和实现,所以在考察字符串反转的时候,会加上一些别的。
LeetCode541.反转字符串II中,题目中的:每隔2k个字符的前k的字符,写了比较复杂的代码进行处理,但是每当需要固定规律一段一段去处理字符串的时候,要想想在for循环的表达式上做做文章了。只要让i+=(2*k),i每次移动2k就可以了,然后判断是否有需要反转的区间。
LeetCode151.翻转字符串的单词中要求翻转字符串里的单词,这道题目综合考察了字符串的多种操作,这道题搞定了,字符串的基础操作就没有问题了。这道题需要先整体反转再对每个单词进行反转,从而可以实现反转字符串中的单词。
KMP的主要思想是当出现字符串不匹配时,可以知道一部分之前已经匹配的文本内容,可以利用这些信息避免从头再去做匹配。
KMP的精髓是前缀表。(前缀表:起始位置到小标i之前(包括i)的子串中,有多大长度的相同前缀后缀)
使用KMP可以解决两类经典的问题:
1.匹配问题:LeetCode28.实现strStr()
2.重复子串问题: LeetCode459.重复的子字符串
前缀:不包含最后一个字符的所有以第一个字符开头的连续子串
后缀:不包含第一个字符的所有以最后一个字符结尾的连续子串
再针对前缀报表到底要不要减一,这其实是不同KMP实现的方式。
KMP比较难以理解,我也只是简单的描述了一下,基础较为薄弱的同学再进行字符串的练习过程中,可以选择跳过这一部分,等算法能力提升了再进行学习。(我也不太懂,后续作者会持续更新)
在代码随想录day1中,就提到了数组中的元素,不能真正的删除,只能被覆盖,但是如果使用暴力发进行求解LeetCode27.移除元素的时间复杂度是O(n^2)无法通过,这时候就可以使用双指针法进行求解。
双指针在效率上的优势:通过两个指针在一个for循环下完成两个for循环的工作。
在LeetCode344.反转字符串中,使用双指针法,定义两个下标,一个在字符串起始位置,一个在字符串末尾位置,两个指针同时向中间移动,并且交换元素,时间复杂度是O(n)。
在替换数字中,使用的是双指针填充字符串的方法,要把这道题做到极致,就不能使用额外的辅助空间。思路就是:先把数组扩充,然后使用双指针从后向前替换数字。
在LeetCode151.翻转字符串里的单词中,使用双指针法,根据题目要求删除多余的空格,使用O(n)的时间复杂度完成了字符串删除类的操作。
有很多同学在删除多余空格的过程中,习惯于使用erase函数,导致很容易写成O(n^2)的时间复杂度。但是使用双指针法,就可以仅用O(n)的时间复杂度就可以实现。具体实现过程,与移除元素过程一致,但是需要多加一步保持住单词间的空格。
反转链表是一道很经典的题目,考察了链表以及指针的熟悉程度
在LeetCode206反转链表中,使用双指针法反转链表,只需要改变链表next指针的指向,直接将链表反转,而不需要重新定义一个新的链表,代码与思路不是很难想到,需要同学们多次的理解练习。
在链表中求环,是双指针在链表中的最经典的英语,在LeetCode142.环形链表II中,我们学习了如何通过双指针判断是否有环。具体实现:
定义一个快指针一个慢指针,都从头结点出发,快指针每次移动两个结点,慢指针每次移动一个结点,如果快指针和慢指针在途中相遇,说明这个链表有环。
我们之前学习过,可以使用哈希表解决两数之和的问题,但是也可以使用双指针法进行求解,只是题目中要求的是两元素的下标,无法使用双指针求解,如果题目改成求具体两个元素的数值就可以了。
虽然可以使用哈希法求解两数之和,但是哈希法并不适用于求解三数之和。因为使用哈希法的过程中要把符合条件的三元组放进vector中,然后再去重,这就非常费时,这就是为什么不使用双指针的原因。
这道题使用双指针法才是最合适的,通过前后两个指针不断向中间逼近,在一个for循环下完成两个for循环的工作。
同样的原理,四数之和,n数之和都是可以求解的