字符串操作
字符串的基本操作对象通常是字符串整体或者其子串,很多时候我们希望对子串进行操作,这是字符串与数组不同的地方之一。且字符串部分操作比数组更加复杂,如比较和连接操作。在c++中,字符串可以用==来实现比较,也可以直接进行连接操作,但是在其他语言如java中不可以直接实现且字符串不可变。
1.查找字符串最长公共前缀
编写一个函数来查找字符串数组中的最长公共前缀。如果不存在公共前缀,返回空字符串 ""
。
输入:strs = ["flower","flow","flight"]
输出:"fl"
输入:strs = ["dog","racecar","car"]
输出:""
思路:由于寻找公共前缀,不妨设置第一个为公共前缀,然后将其与之后的进行比较,删去不同的部分。
这里使用了c++函数erase(),有三种用法:
(1)erase(pos,n); 删除从pos开始的n个字符,例如erase(0,1),删除0位置的一个字符,即删除第一个字符
(2)erase(position); 删除position处的一个字符(position是个string类型的迭代器)
(3)erase(first,last);删除从first到last之间的字符,(first和last都是迭代器)
1 class Solution {
2 public:
3 string longestCommonPrefix(vector<string>& strs) {
4 string same = strs[0];
5 for(int i =1;i<strs.size();i++){
6 for(int j=0;j<same.size();j++){
7 if(same[j] != strs[i][j]) same.erase(j);
8 }
9 }
10 return same;
11 }
12 };
2.最长回文字符串: 力扣官方解法
(1)动态规划:
所以我们要找的最长回文字符串就是满足P(i,j)=true的长度j-i+1最大的部分。
注意:在状态转移方程中,我们是从长度较短的字符串向长度较长的字符串进行转移的,因此一定要注意动态规划的循环顺序。
1 #include <iostream> 2 #include <string> 3 #include <vector> 4 5 using namespace std; 6 7 class Solution { 8 public: 9 string longestPalindrome(string s) { 10 int n = s.size(); 11 if (n < 2) { 12 return s; 13 } 14 15 int maxLen = 1; 16 int begin = 0; 17 // dp[i][j] 表示 s[i..j] 是否是回文串 18 vector<vector<int>> dp(n, vector<int>(n)); 19 // 初始化:所有长度为 1 的子串都是回文串 20 for (int i = 0; i < n; i++) { 21 dp[i][i] = true; 22 } 23 // 递推开始 24 // 先枚举子串长度 25 for (int L = 2; L <= n; L++) { 26 // 枚举左边界,左边界的上限设置可以宽松一些 27 for (int i = 0; i < n; i++) { 28 // 由 L 和 i 可以确定右边界,即 j - i + 1 = L 得 29 int j = L + i - 1; 30 // 如果右边界越界,就可以退出当前循环 31 if (j >= n) { 32 break; 33 } 34 35 if (s[i] != s[j]) { 36 dp[i][j] = false; 37 } else { 38 if (j - i < 3) { 39 dp[i][j] = true; 40 } else { 41 dp[i][j] = dp[i + 1][j - 1]; 42 } 43 } 44 45 // 只要 dp[i][L] == true 成立,就表示子串 s[i..L] 是回文,此时记录回文长度和起始位置 46 if (dp[i][j] && j - i + 1 > maxLen) { 47 maxLen = j - i + 1; 48 begin = i; 49 } 50 } 51 } 52 return s.substr(begin, maxLen); 53 } 54 };
最后部分使用到字符串截取函数substr(),有两种用法:
格式1: substr(string string, int a, int b);
格式2:substr(string string, int a) ;
格式1:
1、string 需要截取的字符串
2、a 截取字符串的开始位置(注:当a等于0或1时,都是从第一位开始截取)
3、b 要截取的字符串的长度
格式2:
1、string 需要截取的字符串
2、a 可以理解为从第a个字符开始截取后面所有的字符串。
(2)中心扩展:
可以看出,这里的边界情况,其实就是回文字符串的中心位置。我们枚举所有的「回文中心」并尝试「扩展」,直到无法扩展为止,此时的回文串长度即为此「回文中心」下的最长回文串长度。我们对所有的长度求出最大值,即可得到最终的答案。
1 class Solution { 2 public: 3 pair<int, int> expandAroundCenter(const string& s, int left, int right) { 4 while (left >= 0 && right < s.size() && s[left] == s[right]) { 5 --left; 6 ++right; 7 } 8 return {left + 1, right - 1}; 9 } 10 11 string longestPalindrome(string s) { 12 int start = 0, end = 0; 13 for (int i = 0; i < s.size(); ++i) { 14 auto [left1, right1] = expandAroundCenter(s, i, i); 15 auto [left2, right2] = expandAroundCenter(s, i, i + 1); 16 if (right1 - left1 > end - start) { 17 start = left1; 18 end = right1; 19 } 20 if (right2 - left2 > end - start) { 21 start = left2; 22 end = right2; 23 } 24 } 25 return s.substr(start, end - start + 1); 26 } 27 };
3.翻转字符串里的单词:
给你一个字符串 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"
解释:如果两个单词间有多余的空格,反转后的字符串需要将单词间的空格减少到仅有一个。
方法一:自行编写函数
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现