欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 资讯 > 代码随想录16 Leetcode151.反转字符串里的单词

代码随想录16 Leetcode151.反转字符串里的单词

2025/5/11 3:23:54 来源:https://blog.csdn.net/m0_74096700/article/details/144881007  浏览:    关键词:代码随想录16 Leetcode151.反转字符串里的单词

给你一个字符串 s ,请你反转字符串中 单词 的顺序。

单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。

返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。

注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。

示例 1:

输入:s = "the sky is blue"
输出:"blue is sky the"

示例 2:

输入:s = "  hello world  "
输出:"world hello"
解释:反转后的字符串中不能存在前导空格和尾随空格。

示例 3:

输入:s = "a good   example"
输出:"example good a"
解释:如果两个单词间有多余的空格,反转后的字符串需要将单词间的空格减少到仅有一个。

思路:

因为空格没有规定,字符串前面后面都可能有空格,而且空格的个数也没有规定

所以我们先把字符串的空格处理好

然后再把字符字符翻转

class Solution {
public:void reverse(string& s, int start, int end){ //翻转,区间写法:左闭右闭 []for (int i = start, j = end; i < j; i++, j--) {swap(s[i], s[j]);}}void removeExtraSpaces(string& s) {//去除所有空格并在相邻单词之间添加空格, 快慢指针。int slow = 0;   //整体思想参考https://programmercarl.com/0027.移除元素.htmlfor (int i = 0; i < s.size(); ++i) { //if (s[i] != ' ') { //遇到非空格就处理,即删除所有空格。if (slow != 0) s[slow++] = ' '; //手动控制空格,给单词之间添加空格。slow != 0说明不是第一个单词,需要在单词前添加空格。while (i < s.size() && s[i] != ' ') { //补上该单词,遇到空格说明单词结束。s[slow++] = s[i++];}}}s.resize(slow); //slow的大小即为去除多余空格后的大小。}string reverseWords(string s) {removeExtraSpaces(s); //去除多余空格,保证单词之间之只有一个空格,且字符串首尾没空格。reverse(s, 0, s.size() - 1);int start = 0; //removeExtraSpaces后保证第一个单词的开始下标一定是0。for (int i = 0; i <= s.size(); ++i) {if (i == s.size() || s[i] == ' ') { //到达空格或者串尾,说明一个单词结束。进行翻转。reverse(s, start, i - 1); //翻转,注意是左闭右闭 []的翻转。start = i + 1; //更新下一个单词的开始下标start}}return s;}
};

KMP算法:

1.暴力算法 时间复杂度是O(m*n)

2.但是KMP算法只需要O(m+n)即可实现

KMP算法(Knuth-Morris-Pratt Algorithm)是一种高效的字符串匹配算法,它通过利用已经部分匹配的结果,避免了重复的比较。与朴素的字符串匹配算法相比,KMP能够在O(n + m)的时间复杂度内完成字符串匹配,其中n是文本串的长度,m是模式串的长度。

KMP算法的核心思想:

KMP算法通过 部分匹配表(通常称为 前缀函数next数组)来减少匹配过程中的重复比较。当发生不匹配时,KMP算法根据部分匹配表跳过一些无意义的比较,从而提高效率。

KMP算法的两个步骤:

  1. 前缀函数的计算:前缀函数用于描述模式串的自身重复结构。它记录了模式串的前后缀的最大匹配长度。
  2. 模式串匹配:在文本串中查找模式串的出现位置,并通过前缀函数进行跳跃,避免不必要的字符比较。

1. **前缀函数(next数组)**的构建

前缀函数是一个数组,next[i]表示模式串中前i个字符的最长公共前后缀的长度。例如,如果模式串是"ABAB",那么:

  • next[0] = 0(没有前缀和后缀)。
  • next[1] = 0(字符"A"没有匹配的前后缀)。
  • next[2] = 1("AB"的最长前后缀是"A")。
  • next[3] = 2("ABA"的最长前后缀是"AB")。

这个数组的作用是,当遇到不匹配时,模式串不需要从头开始重新匹配,而是跳过一部分已经匹配的内容。

2. KMP算法匹配过程

在匹配过程中,如果文本串的当前字符与模式串的当前字符不匹配,就可以利用next数组提供的信息跳到一个新的位置,避免从头开始进行不必要的比较。

#include <iostream>
#include <vector>
using namespace std;// 计算模式串的前缀函数(next数组)
void computeNextArray(const string& pattern, vector<int>& next) {int m = pattern.length();next[0] = -1;  // 初始化next数组的第一个元素int j = -1;for (int i = 1; i < m; i++) {// 当模式串当前字符与之前的字符不匹配时,根据next数组回退while (j >= 0 && pattern[i] != pattern[j + 1]) {j = next[j];  // 回退到上一个可能的前缀位置}// 如果匹配,扩展匹配长度if (pattern[i] == pattern[j + 1]) {j++;}next[i] = j;  // 将当前字符的最长前后缀长度记录到next数组}
}// KMP模式匹配算法
int KMP(const string& text, const string& pattern) {int n = text.length();  // 文本串长度int m = pattern.length();  // 模式串长度// 计算模式串的前缀函数vector<int> next(m);computeNextArray(pattern, next);int i = 0;  // 文本串指针int j = 0;  // 模式串指针while (i < n) {// 当文本串和模式串的当前字符匹配时,两个指针都前进if (text[i] == pattern[j]) {i++;j++;} else {// 当不匹配时,利用next数组跳过不必要的比较if (j > 0) {j = next[j - 1];  // 根据next数组更新模式串的指针} else {i++;  // 如果模式串的第一个字符就不匹配,文本串前进}}// 如果模式串全部匹配完,则返回匹配的位置if (j == m) {return i - j;  // 返回模式串在文本中的起始位置}}return -1;  // 如果没有找到匹配,返回-1
}int main() {string text = "ABABDABACDABABCABAB";  // 文本串string pattern = "ABABCABAB";  // 模式串// 调用KMP算法进行匹配int index = KMP(text, pattern);if (index != -1) {cout << "Pattern found at index " << index << endl;  // 找到匹配时输出位置} else {cout << "Pattern not found." << endl;  // 没有找到匹配时输出}return 0;
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词