第四章 字符串part01
今日任务
- 344.反转字符串
- 541.反转字符串II
- 151.翻转字符串里的单词
详细布置
344.反转字符串
建议: 本题是字符串基础题目,就是考察 reverse 函数的实现,同时也明确一下 平时刷题什么时候用 库函数,什么时候 不用库函数
题目链接/文章讲解/视频讲解:https://programmercarl.com/0344.%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2.html
c++:
class Solution {
public:
void reverseString(vector<char>& s) {
int n = s.size() - 1;
for(int i = 0,j = n;i < j;i++,j--)
{
swap(s[i],s[j]);
}
}
};
java:
class Solution {
public void reverseString(char[] s) {
int n = s.length;
for(int i = 0;i < n / 2;i++){
char tmp = s[i];
s[i] = s[n - i - 1];
s[n - i - 1] = tmp;
}
}
}
541. 反转字符串II
建议:本题又进阶了,自己先去独立做一做,然后在看题解,对代码技巧会有很深的体会。
题目链接/文章讲解/视频讲解:https://programmercarl.com/0541.%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2II.html
c++:
class Solution {
public:
void reverse(string& s,int l,int r)
{
for(int i = l,j = r;i < j;i++,j--)
{
swap(s[i],s[j]);
}
}
string reverseStr(string s, int k) {
int n = s.size();
for(int l = 0;l < n;l += 2 * k)
{
int r = l + k - 1;//右边界
//注意范围 [l,r] 内不足 k个的情况
reverse(s,l,min(r, n - 1));
}
return s;
}
};
java:
模拟
使用 l
和 r
两个指针分别圈出每次需要翻转的“理论”范围,每次翻转完更新 l
和 r
,同时注意范围 [l,r] 内不足 k个的情况(将 r
与真实边界 n - 1
取个 min)。
public String reverseStr(String s, int k) {
char[] cs = s.toCharArray();
int n = s.length();
for(int l = 0;l < n;l = l + 2 * k)
{
int r = l + k - 1;
reverse(cs,l,Math.min(r,n - 1));
}
return String.valueOf(cs);
}
void reverse(char[] cs, int l, int r) {
while(l < r){
char c = cs[l];
cs[l] = cs[r];
cs[r] = c;
l++;r--;
}
151.翻转字符串里的单词
建议:这道题目基本把 刚刚做过的字符串操作 都覆盖了,不过就算知道解题思路,本题代码并不容易写,要多练一练。
题目链接/文章讲解/视频讲解:https://programmercarl.com/0151.%E7%BF%BB%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2%E9%87%8C%E7%9A%84%E5%8D%95%E8%AF%8D.html
c++:
class Solution {
public:
string reverseWords(string s) {
//先对单个单词进行翻转,然后对整体进行翻转,重点在于字符间空格的取出
int k = 0;
for(int i = 0; i < s.size();){
int j = i;
while(j < s.size() && s[j] == ' ') j ++;
if(j == s.size()) break;
i = j;
while(j < s.size() && s[j] != ' ') j ++;
reverse(s.begin() + i,s.begin() + j); //[,),reverse函数是左闭右开的
if(k) s[k++] = ' '; //如果当前处理字符串是第一个字符串,则无需在字符串开头添加空格,否则则增加一个空格
while(i < j) s[k ++] = s[i ++]; //对当前字符串进行复制,使得相邻字符串间只有一个空格
}
s.erase(s.begin() + k,s.end()); //删除结尾的所有空格
reverse(s.begin(),s.end());
return s;
}
};
java:
方法一:双指针
算法解析:
- 倒序遍历字符串 sss ,记录单词左右索引边界 i , j 。
- 每确定一个单词的边界,则将其添加至单词列表 res 。
- 最终,将单词列表拼接为字符串,并返回即可。
class Solution {
public String reverseWords(String s) {
s = s.trim(); // 删除首尾空格
int j = s.length() - 1, i = j;
StringBuilder res = new StringBuilder();
while (i >= 0) {
while (i >= 0 && s.charAt(i) != ' ') i--; // 搜索首个空格
res.append(s.substring(i + 1, j + 1) + " "); // 添加单词
while (i >= 0 && s.charAt(i) == ' ') i--; // 跳过单词间空格
j = i; // j 指向下个单词的尾字符
}
return res.toString().trim(); // 转化为字符串并返回
}
}
方法二:分割 + 倒序
利用 “字符串分割”、“列表倒序” 的内置函数 (面试时不建议使用) ,可简便地实现本题的字符串翻转要求。
Java : 以空格为分割符完成字符串分割后,若两单词间有 x*>1 个空格,则在单词列表strs 中,此两单词间会多出x−1 个 “空单词” (即 ""
)。解决方法:倒序遍历单词列表,并将单词逐个添加至 StringBuilder ,遇到空单词时跳过。
class Solution {
public String reverseWords(String s) {
String[] strs = s.trim().split(" "); // 删除首尾空格,分割字符串
StringBuilder res = new StringBuilder();
for (int i = strs.length - 1; i >= 0; i--) { // 倒序遍历单词列表
if (strs[i].equals("")) continue; // 遇到空单词则跳过
res.append(strs[i] + " "); // 将单词拼接至 StringBuilder
}
return res.toString().trim(); // 转化为字符串,删除尾部空格,并返回
}
}