【LeetCode】字符串反转及其衍生问题(7)

(一)基础:字符串反转

题目(Easy):344. 反转字符串

题目描述:

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。

不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。

你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。

示例 1:

输入:["h","e","l","l","o"]
输出:["o","l","l","e","h"]

解题思路:

  本题是字符串反转的最基本算法,要反转一个字符串,可以采用首尾双指针的方式,首尾互换后移动指针即可。

代码实现:

	public void reverseString(char[] s) {
        int i=0,j=s.length-1;
        while(i<j){
            char temp=s[i];
            s[i]=s[j];
            s[j]=temp;
            i++;
            j--;
        }
    }

(二)反转字符串II

题目(Easy):541. 反转字符串 II

题目描述:

给定一个字符串和一个整数 k,你需要对从字符串开头算起的每个 2k 个字符的前k个字符进行反转。如果剩余少于 k 个字符,则将剩余的所有全部反转。如果有小于 2k 但大于或等于 k 个字符,则反转前 k 个字符,并将剩余的字符保持原样。

示例:

	输入: s = "abcdefg", k = 2
	输出: "bacdfeg"

解题思路:

  本题比较简单,是字符串反转的一个直接应用,可以直接看代码实现。

代码实现:

class Solution {
    public String reverseStr(String s, int k) {
        char[] strArr=s.toCharArray();
        int len=strArr.length;
        
        for(int begin=0;begin<len;begin+=(k*2)){
            int i=begin,j=Math.min(begin+k-1,len-1);  //注意j的判断
            reverse(strArr,i,j);
        }
        
        return new String(strArr);
    }
    //字符串反转
    public void reverse(char[] s,int begin,int end){
        int i=begin,j=end;
        while(i<j){
            char temp=s[i];
            s[i]=s[j];
            s[j]=temp;
            i++;
            j--;
        }
    }
}

(三)反转字符串中的单词 III

题目(Easy):反转字符串中的单词 III

题目描述:

给定一个字符串,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。

示例 1:

	输入: "Let's take LeetCode contest"
	输出: "s'teL ekat edoCteeL tsetnoc" 

注意:在字符串中,每个单词由单个空格分隔,并且字符串中不会有任何额外的空格。


解题思路:

  同样采用两个指针,遇到空格,则反转对应的单词,依次判断即可。

代码实现:

class Solution {
    public String reverseWords(String s) {
        char[] strArr = s.toCharArray();
        int begin=0;
        for(int i=0;i<strArr.length;i++){
            if(strArr[i]==' '){
                reverse(strArr,begin,i-1);
                begin=i+1;
            }
        }
        reverse(strArr,begin,strArr.length-1);
        return new String(strArr);
    }
    public void reverse(char[] s,int begin,int end){
        int i=begin,j=end;
        while(i<j){
            char temp=s[i];
            s[i]=s[j];
            s[j]=temp;
            i++;
            j--;
        }
    }
}

(四)左旋转字符串

题目(Easy):面试题58 - II. 左旋转字符串【剑指Offer】43、左旋转字符串

题目描述:

字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。

示例 1:

	输入: s = "abcdefg", k = 2
	输出: "cdefgab"

示例 2:

	输入: s = "lrloseumgh", k = 6
	输出: "umghlrlose"

解题思路:

  本题也是字符串反转的衍生题目,具体思路可以见另一篇博文:【剑指Offer】43、左旋转字符串

代码实现:

class Solution {
    public String reverseLeftWords(String s, int n) {
        if(s==null || s.length()==0)
            return s;
        int len=s.length();
        n=n%len;

        char[] strArr=s.toCharArray();
        reverse(strArr,0,n-1);  //三次反转
        reverse(strArr,n,len-1);
        reverse(strArr,0,len-1);
        return new String(strArr);
    }
    //字符串反转
    public void reverse(char[] strArr,int begin, int end){
        int i=begin,j=end;
        while(i<j){
            char temp=strArr[i];
            strArr[i]=strArr[j];
            strArr[j]=temp;
            i++;
            j--;
        }
    }
}

(五)反转单词序列

题目:【剑指Offer】44、反转单词序列

题目描述:

牛客最近来了一个新员工Fish,每天早晨总是会拿着一本英文杂志,写些句子在本子上。同事Cat对Fish写的内容颇感兴趣,有一天他向Fish借来翻看,但却读不懂它的意思。例如,“student. a am I”。后来才意识到,这家伙原来把句子单词的顺序翻转了,正确的句子应该是“I am a student.”。Cat对一一的翻转这些单词顺序可不在行,你能帮助他么?


解题思路:

本题相对比较简单,但是在面试中经常遇到,流传甚广。其主要思路也简洁明了,主要分为以下两步:

第一步:反转整个序列中所有的字符,这时会发现不但反转了单词的顺序,单词中的字母顺序也被反转,因此需要第二步的调整。

第二步:以空格为分隔,依次反转每个单词,即让每个单词会到原来的正常顺序。(这也就是第三题)

代码实现:

public class Solution {
    //先翻转整个字符串,再逐一翻转每个单词
    public String ReverseSentence(String str) {
        if(str==null)
            return null;
        char[] strArr=str.toCharArray();
        reverseStr(strArr,0,strArr.length-1); //翻转整个字符串
        int begin=0;
        for(int i=0;i<strArr.length;i++){
            if(strArr[i]==' '){
                reverseStr(strArr,begin,i-1);
                begin=i+1;
            }
        }
        reverseStr(strArr,begin,strArr.length-1); //最后一个单词后没有空格
        return new String(strArr);
    }
    
    public void reverseStr(char[] array,int begin,int end){ //反转字符串,前后指针
        for(;begin<end;begin++,end--){
            char c=array[begin];
            array[begin]=array[end];
            array[end]=c;
        }
    }
}

(六)反转字符串中的元音字母

题目(Easy):345. 反转字符串中的元音字母

题目描述:

编写一个函数,以字符串作为输入,反转该字符串中的元音字母。

元音字母:a,e,i,o,u

示例 1:

输入: "hello"
输出: "holle"

示例 2:

输入: "leetcode"
输出: "leotcede"

解题思路:

  使用前后双指针,找到元音字母,然后交换即可。

代码实现:

class Solution {
    public String reverseVowels(String s) {
        if(s==null || s.length()==0)
            return s;
        char[] strArr=s.toCharArray();
        int i=0,j=s.length()-1;
        while(i<j){
            while(i<s.length() && !check(strArr[i]))
                i++;
            while(j>=0 && !check(strArr[j]))
                j--;
            
            if(i>=j)
                break;

            //i和j互换
            char temp=strArr[i];
            strArr[i++]=strArr[j];
            strArr[j--]=temp;
        }
        return new String(strArr);
    }

    public boolean check(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;
    }
}

(七)仅仅反转字母

题目(Easy):917. 仅仅反转字母

题目描述:

给定一个字符串 S,返回 “反转后的” 字符串,其中不是字母的字符都保留在原地,而所有字母的位置发生反转。

示例 1:

输入:"ab-cd"
输出:"dc-ba"

示例 2:

输入:"a-bC-dEf-ghIj"
输出:"j-Ih-gfE-dCba"

解题思路:

  类似于反转字符串中的元音字母,前后双指针交换,只是判断条件不同。

代码实现:

class Solution {
    public String reverseOnlyLetters(String S) {
        if(S==null || S.length()==0)
            return S;
        char[] strArr=S.toCharArray();
        int i=0,j=strArr.length-1;
        while(i<j){
            while(i<strArr.length && !check(strArr[i]))
                i++;
            while(j>=0 && !check(strArr[j]))
                j--;
            if(i>=j)
                break;
            
            //交换
            char temp=strArr[i];
            strArr[i++]=strArr[j];
            strArr[j--]=temp;
        }
        return new String(strArr);
    }
    public boolean check(char c){
        if(c>='a' && c<='z')
            return true;
        if(c>='A' && c<='Z')
            return true;
        return false;
    }
}

总结:

本文总结了关于字符串反转的七道题目,相对来说比较简单,但是这是字符串类题目的基础,特别是左旋转字符串和反转单词序列两题体现了字符串反转的妙用。

posted @ 2020-03-18 18:18  gzshan  阅读(1113)  评论(0编辑  收藏  举报