力扣题部分的28.找出字符串第一个匹配项的下标和459.重复的子字符串两题由于涉及KMP算法暂时跳过(没学明白QWQ),过段时间单独开一篇博客讲
力扣题部分
151.翻转字符串里的单词
题目链接:. - 力扣(LeetCode)
题面:
给你一个字符串 s
,请你反转字符串中 单词 的顺序。
单词 是由非空格字符组成的字符串。s
中使用至少一个空格将字符串中的 单词 分隔开。
返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。
注意:输入字符串 s
中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。
我的思路(不推荐):
我的想法和大多数人差不多。一个一个单词遍历过来,提取然后加到一个空串里面(反方向加)
为什么不推荐呢,substr的时间复杂度是O(n),在for循环里用函数复杂度是O(n^2)。实际上,这道题的最优解时间复杂度可以到O(n)。
代码实现:
思路(双重反转字符串 + 双指针):
没接触过这个其实挺难想的,举个例子:
s = the sky is blue (原字符串)
s = eulb si yks eht (对所有的字符串取反)
s = bule is sky the (分别对各个单词取反)
通过两次取反,单词内部顺序就负负得正了,然后由于第二次没有对单词位置取反仅仅只是对单词内部取反,导致字符串单词顺序实现反序,
然而还有一个问题没解决:去空格。
一想到去空格,可能有人想到erase函数,比如用下面这段代码
void removeExtraSpaces(string& s) {
for (int i = s.size() - 1; i > 0; i--) {
if (s[i] == s[i - 1] && s[i] == ' ') {
s.erase(s.begin() + i);
}
}
// 删除字符串最后面的空格
if (s.size() > 0 && s[s.size() - 1] == ' ') {
s.erase(s.begin() + s.size() - 1);
}
// 删除字符串最前面的空格
if (s.size() > 0 && s[0] == ' ') {
s.erase(s.begin());
}
}
然而这又产生了一个我们本来想避免的问题——时间复杂度。
和substr一样,erase的时间复杂度是O(n),像这样for循环里面用erase,时间复杂度又变成O(n^2)了。好不容易将前面的复杂度降到O(n),去空白让我们又回到了原点。
难道没有别的办法吗? 当然有,甚至我在第一天接触过(第27题.移除元素)。
代码随想录算法训练营第一天|数组理论基础,704. 二分查找,34.在排序数组中查找元素的第一个位置和最后一个位置 27. 移除元素-优快云博客 没错,又是双指针,与上次不同的是,我们需要在去除完所有空格后为单词间留一个空格,这也好办,先去除前面的和后面的空格,之后再为连续的多个空格增加条件,然后就可以将时间复杂度降到O(n)了。
代码实现:
卡码网题部分
55.右旋转字符串
题目链接:55. 右旋字符串(第八期模拟笔试)
题面:
字符串的右旋转操作是把字符串尾部的若干个字符转移到字符串的前面。给定一个字符串 s 和一个正整数 k,请编写一个函数,将字符串中的后面 k 个字符移到字符串的前面,实现字符串的右旋转操作。
例如,对于输入字符串 "abcdefg" 和整数 2,函数应该将其转换为 "fgabcde"。
要求:不能申请额外空间,只能在本串上操作。
思路(双重反转字符串):
和前一道题确实有异曲同工之妙。
还是整体反转和局部(被k分成的两部分)分别反转,甚至更简单,不需要考虑空格。
代码实现:
字符串总结
文章链接:代码随想录
文章摘要:
定义:
字符串是若干字符组成的有限序列,也可以理解为是一个字符数组,但是很多语言对字符串做了特殊的规定,接下来我来说一说C/C++中的字符串。
在C语言中,把一个字符串存入一个数组时,也把结束符 '\0'存入数组,并以此作为该字符串是否结束的标志。
要不要使用库函数
这个之前day7的时候讲到过,这边再说明一下使用建议:
如果题目关键的部分直接用库函数就可以解决,建议不要使用库函数。
如果库函数仅仅是 解题过程中的一小部分,并且你已经很清楚这个库函数的内部实现原理的话,可以考虑使用库函数
双指针回顾
文章链接:代码随想录
文章摘要:
数组篇
用到的基本是移除元素,将复杂度从O(n^2)降到O(n)。
字符串篇
除了和数组篇一样的移除元素,双指针在字符串还有一个用途:原地反转字符串。
链表篇
在链表中求环,应该是双指针在链表里最经典的应用,之前在day4讲到过。
当然还有反转链表了,也是很重要,需要反复复习掌握的。
N数之和篇
双指针是真的占了day7的大头(甚至比哈希表还多),两数之和还能用哈希凑合,到了三数及以上,哈希就没体现出多大优势了,相比之下,双指针的重要性就凸显出来了。
总结:
字符串有很多好用的函数,不过使用时最好考虑一下时间复杂度的问题,不然就会有可能明明时间复杂度能降下来的却没降下来。还有双指针法的运用,基本上是通过前后两个指针不断向中间逼近,在一个for循环下完成两个for循环的工作。还有就是KMP算法了,KMP算法是字符串查找最重要的算法,但彻底理解KMP并不容易,更别说写在博客里讲明白了,所以我只能暂时先放着有空再讲了。