字符串反转的题型

1.字符串逆序的第一种类型,即反转字符串,力扣557. 反转字符串中的单词

  void reverseString(char* s, int sSize){
       int left=0;
       int right=sSize-1;
       while(left<right){
           char tmp=s[left];
           s[left++]=s[right];
           s[right--]=tmp;
       }
       return *s;
}

思路即为用两个指针,一个指针指向第一个元素,另一个指针指向最后一个元素,进行前后反转
2.力扣541. 反转字符串 II
给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。
如果剩余字符少于 k 个,则将剩余字符全部反转。
如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。

该题的思路为:反转k个字符,之后跳过k个字符,如此循环,如果剩余的字符小于k个大于2k个,则反转前k个,剩下的不变。
如果剩余的字符小于k个,那么全部反转
该题具体实现时,用到了局部反转的思想,这个在之后的题目也会用到。即规定反转开始的位置和反转结束的位置,在其中进行如题目一所示的字符串逆序
开始起始的位置start为0,起始end要判断与len(即字符串长度)的关系 int end=k<len?k-1:len-1 看首先要反转的k个字符的k是否小于字符串长度,如果小于那么结束位置可以为k-1,否则为len-1(k-1就已经越界了)`

char*reverse(char* s,int key){
    int len=strlen(s);
    int start=0;
    int end=k<len?k-1:len-1;//看k是否比数组的总长度要小,如果小,那么初始的end(end是个下标而非长度)就为k-1,否则为len-1
    while(start<len&&end<len){//在确保start和end都小于len的情况下
           int i,j=0;
        for( i=start, j=end;i<j;i++,j--){
            s[i]^=s[j];
            s[j]^=s[i];
            s[i]^=s[j];
        }
        start+=2*k;//每次局部反转完之后start,end都会发生相应的改变,start会向后移2k,end也会移2k
        end=end+2*k<len-1?end+2*k:len-1;
    }
    return s;
}`

3.用递归的方式实现字符串逆序

 void reverse_string(char* arr)
    {
        int len = strlen(arr);
        char tmp = *arr;
        *arr = *(arr + len - 1);

        *(arr + len - 1) = '\0';//如果此时不将最后一个置为'\0',无法将中间要逆序的部分当做字符串来看待,故加入一个临时的'\0',等待逆序完了再将最后一位放入tmp
        if (strlen(arr + 1) >= 2)
            reverse_string(arr + 1);

        *(arr + len - 1) = tmp;
    }

4.反转字符串三 力扣557. 反转字符串中的单词 III
给定一个字符串,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。
示例:
输入:“Let’s take LeetCode contest”
输出:“s’teL ekat edoCteeL tsetnoc”

char *reverseword(char *s){
    int length=strlen(s);
    int i=0;
    while(i<length){
        int start=i;
        while(i<length&&s[i]!=' '){
            i++;
        }
        int left=start;    //左指针
        int right=i-1; //右指针,因为i已经是在空格位置了,所以right需要是i-1
        while(left<right){
            char tmp=s[left];
            s[left]=s[right];
            s[right]=tmp;
            left++;
            right--;
        }
      while(i<length&&s[i]==' '){//该单词反转完成,反转下一个单词
        i++;//将i由指向空格处改为指向下一个字符处
      }
    }
    return s;
}

5.反转字符串中的元音字母
给你一个字符串 s ,仅反转字符串中的所有元音字母,并返回结果字符串。
元音字母包括 ‘a’、‘e’、‘i’、‘o’、‘u’,且可能以大小写两种形式出现不止一次。
法一:利用双指针法判断

//判断是不是元音
bool isVowel(char c){
    if(c == 'a' || c == 'e' ||c == 'i' ||c == 'o' ||c == 'u' || c == 'A' ||c == 'E' ||c == 'I' ||c == 'O' ||c == 'U')
        return true;
    return false;
}

char * reverseVowels(char * s){
    int left = 0;
    int right = strlen(s)-1;
    printf("%s\n",s);
    while(left < right){
        //如果不是元音,移动下标
        if(!isVowel(s[left])){
            left++;
            if(left >right)
                return s; //注意每当left>right时就会直接跳出,下面都是如此
        }
        if(!isVowel(s[right])){
            right--;
            if(left >right)
                return s;
        }
        //左右都是元音,开始交换
        if(isVowel(s[left]) && isVowel(s[right])){
            char temp = s[left];
            s[left] = s[right];
            s[right] = temp;
            left++;
            right--;
            if(left >right)
                return s;
        }
    }
    return s;
}

利用下标进行原数组的反转
利用循环遍历原数组,并且开辟一个新数组,遇到元音字母的时候,将该元音字母的下标存入到新数组中,并且记录新数组的长度,当新数组的长度大于等于2时,则利用新数组中存的元音字母下标对原数组中的元音字母进行反转(逆序)。

char * reverseVowels(char * s){
    char vowel[]={"aoeiuAOEIU"};
    int length=strlen(s);
    int pos[300000]={0};
    int m=0;
    for(int i=0;i<length;i++){
        if(strchr(vowel,s[i])){
            pos[m]=i;//**开辟新数组记录原字符串中元音字母的下标**
            m++;
        }
    }
    if(m>=2){
        for(int i=0;i<m/2;i++){//**利用下标对原字符串中的元音字母进行逆序**
            char temp=s[pos[i]];
            s[pos[i]]=s[pos[m-i-1]];
            s[pos[m-i-1]]=temp;
        }
    }
    return s;
}

6.牛客OR62 倒置字符串 I like beijing. 经过函数后变为 beijing. like I
总体思路:先将整个字符串反转,再将每个单词反转
值得注意的是,将整个字符串反转与将每个单词反转用一个函数,而如果用题目一的函数,则无法很好地反转,故此处还是局部反转思想,传入函数的参数为要反转的边界值

void reverse(char *left,char *right){
	assert(left&&right);//首先断言,看看是否为空指针
    while(left<right){
    	char tmp=*left;
    	*left=*right;
    	*right=tmp;
    	left++;
    	right--;
	}
}
int main(){
	char arr[101]={0};
	gets(arr);
	int len=strlen(arr);
	reverse(arr,arr+len-1);//首先将整个字符串反转
	char* cur=arr;
	while(cur){
		char* start=cur;//start来定位每次cur的初始位置
		while(*cur!=' '&&*cur!='\0'){//cur定位的是翻转每一个单词的最后一个位置,不到空格或者不到'\0',cur会一直向后移动
			cur++;
		}
		reverse(start,cur-1);
	    cur++;//此时cur指向空格处,cur++来到了下一个单词
	}
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值