1 替代空格
LeetCode:替代空格
利用扩充的字符串和双指针,利用前后长度的区别来移动两指针直到相遇为止。
class Solution {
public:
string replaceSpace(string s) {
//计算空格数
int spaceCount=0;
for(int i=0;i<s.size();i++)
{
if(s[i]==' ')
++spaceCount;
}
//记录前后长度,并扩充
int old_size=s.size();
s.resize(s.size()+2*spaceCount);
int new_size=s.size();
//双指针
int i=old_size-1;
int j=new_size-1;
while(i<j)
{
if(s[i]!=' ')
{
s[j]=s[i];
}
else
{
s[j--]='0';
s[j--]='2';
s[j]='%';
}
--i;
--j;
}
return s;
}
};
2 反转字符串中的单词
LeetCode:反转字符串中的单词
本题考察在不额外利用空间的情况下对字符串进行反转,并且考虑前导空格、尾随空格与多余空格的情况。
事实上反转单词可以分为三个步骤进行:去除多余空格、反转整个字符串、反转每个单词。
class Solution {
public:
//去除多余空格
void removeExtraSpace(string& s)
{
//双指针
//快慢指针,快指针遍历原字符串,慢指针更新新字符串
int fast=0;
int slow=0;
//前导空格
while(s[fast]==' ')
++fast;
//中间更新新字符串
//每个单词后面都会有一个空格(末尾除外)
for(;fast<s.size();fast++)
{
if(fast>0 && s[fast]==' ' && s[fast-1]==' ')
{
continue;
}
else
{
s[slow++]=s[fast];
}
}
if(s[slow-1]==' ')
s.resize(slow-1);
else
s.resize(slow);
}
//部分翻转
void reversePart(string& s,int start,int end)
{
while(start<end)
{
char tmp=s[start];
s[start]=s[end];
s[end]=tmp;
++start;
--end;
}
}
string reverseWords(string s) {
//去除空格
removeExtraSpace(s);
//句子翻转
reversePart(s,0,s.size()-1);
//双指针定位单词
int left=0;
int right=0;
while(right<s.size())
{
if(right==s.size()-1 || s[right+1]==' ')
{
reversePart(s,left,right);
right+=2;
left=right;
}
else
{
++right;
}
}
return s;
}
};
3 有效的字母异位词
LeetCode:有效的字母异位词
经典的一道哈希计数题,字母异位词代表着两个单词的各个字母计数理应一致,使用哈希再简单不过。
class Solution {
public:
bool isAnagram(string s, string t) {
if(s.size()!=t.size())return false;
//记录各个字母的个数
int record[26]={0};
int size=s.size();
for(int i=0;i<size;++i)
{
++record[s[i]-'a'];
--record[t[i]-'a'];
}
for(int i=0;i<26;++i)
{
if(record[i]!=0)
return false;
}
return true;
}
};
4 反转字符串II
LeetCode:反转字符串II
十分简单的一道题,过。
class Solution {
public:
void reversePart(string& s,int start,int end)
{
while(start<end)
{
char tmp=s[start];
s[start]=s[end];
s[end]=tmp;
++start;
--end;
}
}
string reverseStr(string s, int k) {
int size=s.size();
int k_count=size/(2*k);
//前k个2k进行翻转
for(int i=0;i<k_count;i++)
{
reversePart(s,2*k*i,2*k*i+k-1);
}
//最后不足2k的进行处理
int length=min(k,size%(2*k));
reversePart(s,2*k*k_count,2*k*k_count+length-1);
return s;
}
};
5 左旋转字符串
LeetCode:左旋转字符串
如果利用额外空间,这将是一道十分简单的题目。但在不能使用额外空间的情况下,那么,左旋转字符串将等效于三次翻转:左Part翻转+右Part翻转+整体翻转。
class Solution {
public:
void reversePart(string& s,int start,int end)
{
while(start<end)
{
char tmp=s[start];
s[start]=s[end];
s[end]=tmp;
++start;
--end;
}
}
string reverseLeftWords(string s, int n) {
//想象为三次翻转
//两次局部反转+一次整体反转
reversePart(s,0,n-1);
reversePart(s,n,s.size()-1);
reversePart(s,0,s.size()-1);
return s;
}
};
6 总结
今天摆了,没什么好说的。因为下午捣鼓ChatGPT的缘故,没有怎么花时间进行刷题和学习。另外早上一节课,下午当助教上一节课,晚上又一节课,只能给自己找找借口偷懒了。
明天开始对字符串的学习将集中于KMP这个大名鼎鼎的算法,恐怕博客也将不只是单纯的LeetCode展示了。
另外开始学习极简主义的MarkDown美学,除了加粗和标题,别的已经懒得用了。
——2023.2.21