目录
344.反转字符串(后几个题的基础)
题目链接:力扣
双指针
void reverseString(char* s, int sSize){
int left=0;
int right=sSize-1;
char temp='\0';
while(left<right){
temp=s[left];s[left]=s[right];s[right]=temp;
left++;right--;
}
}
541.反转字符串II
题目链接:力扣
题目描述:
给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。
如果剩余字符少于 k 个,则将剩余字符全部反转。
如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。
示例:输入:s = "abcdefg", k = 2
输出:"bacdfeg"
这个题目描述让人很难理解!
说白了就是:每隔2k个反转前k个,尾数小于等于k个时候全部反转,尾数大于k个还是翻转前k个。
代码随想录中的解法比这个简洁,时间复杂度和空间复杂度差别不大。
//反转下标从left到right的部分
void reverse(char *s,int left,int right){
char temp='\0';
while(left<right){
temp=s[left];
s[left]=s[right];
s[right]=temp;
left++;right--;
}
}
char * reverseStr(char * s, int k){
int left=0;int right=k-1;
int num=strlen(s)/(2*k);
//处理N*2k的部分
while(num--){
reverse(s,left,right);
left+=2*k;
right+=2*k;
}
//剩余部分小于k全部反转
if(strlen(s)%(2*k)<k){
reverse(s,left,strlen(s)-1);
}
//剩余部分介于k-2k之间,反转前k项
if(strlen(s)%(2*k)>=k){
reverse(s,left,left+k-1);
}
return s;
}
剑指Offer 05.替换空格
题目链接:力扣
题目描述:请实现一个函数,把字符串
s
中的每个空格替换成"%20"。
为减少空间的浪费,先计算出空格的个数,精准定义替换后数组的大小,时间复杂度仍是O(n)。
char* replaceSpace(char* s){
int count=0;
//计算空格个数,精准确定替换后数组大小
for(int i=0;i<strlen(s);i++){
if(s[i]==' '){
count++;
}
}
char * ret=(char *)malloc(strlen(s)+2*count+1);
int index=0;
for(int i=0;i<strlen(s);i++){
//为空格的替换
if(s[i]==' '){
ret[index++]='%';
ret[index++]='2';
ret[index++]='0';
}else{
ret[index++]=s[i];
}
}
ret[index]='\0';
return ret;
}
151.翻转字符串里的单词
题目链接:力扣
题目描述:给你一个字符串 s ,请你反转字符串中 单词 的顺序。
单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。
返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。
注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。
示例: 输入:s ="the sky is blue"
输出:”blue is sky the“
注意:反转后的字符串中不能存在前导空格和尾随空格;
如果两个单词间有多余的空格,反转后的字符串需要将单词间的空格减少到仅有一个。
- 先规范字符串内的空格,去除前后空格、中间空格只保留一个。
- 全局反转,也就是将"the sky is blue"--->"eulb si yks ehy"。
- 反转每一个单词。"eulb si yks ehy"--->"blue is sky the"。
对于第一步,规范空格,我的过程太耗时,之后再做对比
void erase(char* s){
int slow=0;int fast=0;
//跳过前面空格
while(s[fast++]==' ');
//处理中间空格,并且末尾最多一个空格
for(fast=fast-1;fast<strlen(s);fast++){
if(s[fast]!=' '){
s[slow++]=s[fast];
}else{
if(s[slow-1]!=' ')
s[slow++]=' ';
}
}
//去除末尾空格
if(s[slow-1]==' ') s[slow-1]='\0';
else s[slow]='\0';
}
void reverse(char *s,int left,int right){
char temp='\0';
while(left<right){
temp=s[left];
s[left]=s[right];
s[right]=temp;
left++;right--;
}
}
char * reverseWords(char * s){
//规范空格
erase(s);
//整体反转
reverse(s,0,strlen(s)-1);
//反转每个单词
int left=0;int right=0;
for(int i=0;i<strlen(s);i++){
if(s[right]==' '){
reverse(s,left,right-1);
left=right+1;
}
right++;
}
//处理最后一个单词
reverse(s,left,right-1);
return s;
}
剑指Offer 58-II.左旋转字符串
题目链接:力扣
题目描述:
字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。
示例:输入: s = abcdefg, k = 2
输出: "cdefgab"
1.笨办法-额外开辟空间
这个就很容易想到了,额外开辟空间,先存放N之后的元素再存放N之前的元素。
char* reverseLeftWords(char* s, int n){
char *ret=(char *)malloc(strlen(s)+1);
int slow=0;
int fast=n;
int index=0;
for(;fast<strlen(s);fast++){
ret[index++]=s[fast];
}
for(;slow<n;slow++){
ret[index++]=s[slow];
}
ret[index]='\0';
return ret;
}
2.全局反转+局部反转
很好理解但得能想的到,思考剑指offer05.替换空格
- 先全局反转,也就是将"abcdefg"--->"gfedcba"(n=2)
- 局部反转前str(s)-n项,也就是将"gfedcba"--->"cdefgba"
- 局部反转后n项,也就是将"cdefgba"--->"cdefgab"。最终实现左旋转n个字符串。
void reverse(char* s,int left,int right){
char temp='\0';
while(left<right){
temp=s[left];
s[left]=s[right];
s[right]=temp;
left++;
right--;
}
}
char* reverseLeftWords(char* s, int n){
//全局反转
reverse(s,0,strlen(s)-1);
//局部反转前strlen(s)-n项
reverse(s,0,strlen(s)-1-n);
//局部反转后n项
reverse(s,strlen(s)-n,strlen(s)-1);
return s;
}