逆序问题344、541、345、917、557

三种解法思路:

  • 双指针方式。一般利用s.toCharArray()转换成数组比较便于操作;最后再利用new String(arr)将数组转成字符串返回即可。
  • 利用栈进行操作。可以使用StringBuilder作为接受出栈字符的容器。注意:如果想通过“+”进行链接出栈字符容易导致算法超时。在执行速度上StringBuilder > StringBuffer >String.
  • 利用new StringBuffer(s).reverse().toString() 一行代码解决。
    注:StringBuilder和StringBuffer类似于String类,区别在于String类是不可以改变的。
  • 如果多任务并发访问,就使用StringBuffer, 因为这种情况下需要同步以防止StringBuffer崩溃
  • 如果是单任务访问,使用StringBuilder会更有效。
    StringBuffer和StringBuilder中的构造方法和其他方法几乎是完全一样的。

算法运行速度:一般双指针的方式都比较快。

344、541、345、917、557这几道题都是leetCode里面关于字符串逆序Easy等级的题目,在这里按照难度排序。后面的题目可以借鉴前面题目的思路。

344. Reverse String

<String>逆序问题344、541、345、917、557_第1张图片
image.png

解法一:双指针标准解法

//双指针标准解法
class Solution {
    public String reverseString(String s) {
        char[] arr = s.toCharArray();
        int i = 0;
        int j = arr.length-1;
        while(i < j){
            char temp = arr[i];
            arr[i++]=arr[j];
            arr[j--]=temp;
        }
        return new String(arr);
    }
}
image.png

解法二:利用栈进行操作

//使用栈
class Solution {
    public String reverseString(String s) {
        // Stack stack = new Stack();
        // for(char c : s.toCharArray())
        //     stack.push(""+c);
        Stack stack = new Stack();
        for(char c : s.toCharArray())
            stack.push(c);
        StringBuilder result = new StringBuilder();
        while(!stack.isEmpty())
            result.append(stack.pop());
        return result.toString();
    }
}
image.png

解法三:利用StringBuffer

class Solution {
    public String reverseString(String s) {
        return new StringBuffer(s).reverse().toString();
    }
}
image.png

541. Reverse String II

<String>逆序问题344、541、345、917、557_第2张图片
image.png

分析:该问题本质还是进行字符串逆序的操作。只不过多了一个范围的界定,在代码中会体现在两个方面:1.多一个外循环,找到每次要操作的字符串的开头;2.会带来一些边界问题。由于需要进行边界问题的判断,这时候选择双指针的方式更便于操作。
边界判断主要会出现在最后一次循环中,因为有可能剩下的字符个数不足2k甚至不足k,只有当剩下字符个数不足k的时候需要进行逆序操作的字符个数会和前面的操作有所不同(前面都是对k个字符进行逆序操作的)

class Solution {
    public String reverseStr(String s, int k) {
        char[] arr = s.toCharArray();
        for(int start = 0; start < arr.length; start+=2*k){
            //双指针逆序操作
            int i = start;
            int j = Math.min(start+k-1, arr.length-1);//逆序操作的边界限定
            while(i
image.png

345 Reverse Vowels of a String

<String>逆序问题344、541、345、917、557_第3张图片
image.png

分析:
只对元音字母进行逆序。最简单的思路还是双指针解法。从前面往后找到的第一个元音字母与从后往前找到的第一元音字母进行交换。利用字符串的contains方法判断该元素是否为元音字母。注意s变成数组之后,每个数组元素里面存的是char型的元素,通过a[i]+""变成String型。

public class Solution {    
    public String reverseVowels(String s) {
        String vowels = "aoeiuAOEIU";
        char[] a = s.toCharArray();
        int i = 0;
        int j = a.length - 1;
        while (i < j) {
            while (i < j && !vowels.contains(a[i] + "")) {
                i++;
            }
            while (i < j && !vowels.contains(a[j] + "")) {
                j--;
            }
            if (i < j) {
                char c = a[i];
                a[i++] = a[j];
                a[j--] = c;
            }
        }
        return new String(a);
    }
}

917 Reverse Only Letters

<String>逆序问题344、541、345、917、557_第4张图片
image.png

解法一:双指针方式

class Solution {
    public String reverseOnlyLetters(String S) {
        if(S==null)
            return S;
        char[] arr = S.toCharArray();
        int start = 0;
        int end = arr.length-1;
        while(start

解法二:利用栈

思路:如果没有其他字符,那么该问题就是最简单的逆序问题。将字符压入栈中,然后在从前往后遍历一次字符串,如果原字符串的位置为字符,那么从栈里弹出一个字符放入。

//使用栈
class Solution {
    public String reverseOnlyLetters(String S) {
        char[] arr = S.toCharArray();
        Stack stack = new Stack();
        //将字符压入栈中
        for(char c : arr)
            if(Character.isLetter(c))
                stack.push(c);
        
        StringBuilder ans = new StringBuilder();
        //第二次遍历
        for(char c : arr){
            if(Character.isLetter(c))
                ans.append(stack.pop());
            else
                ans.append(c);
        }
        return ans.toString();
    }
}

557 Reverse Words in String III

<String>逆序问题344、541、345、917、557_第5张图片
image.png

分析:该题通过split函数获得单词数组之后,就完全是最简单的字符串逆序问题了。
leetcode上给出了两种解法,比较多的用到了StringBuilder和StringBuffer的操作

方法一:

class Solution {
    public String reverseWords(String s) {
        String[] words = s.split(" ");
        StringBuilder ans = new StringBuilder();
        for(String word : words)
            ans.append(new StringBuffer(word).reverse().toString()+" ");
        return ans.toString().trim();
    }
}

方法二:自己实现了split和reverse函数

public class Solution {
    public String reverseWords(String s) {
        String words[] = split(s);
        StringBuilder res=new StringBuilder();
        for (String word: words)
            res.append(reverse(word) + " ");
        return res.toString().trim();
    }
    public String[] split(String s) {
        ArrayList < String > words = new ArrayList < > ();
        StringBuilder word = new StringBuilder();
        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) == ' ') {
                words.add(word.toString());
                word = new StringBuilder();
            } else
                word.append( s.charAt(i));
        }
        words.add(word.toString());
        return words.toArray(new String[words.size()]);
    }
    public String reverse(String s) {
      StringBuilder res=new StringBuilder();
        for (int i = 0; i < s.length(); i++)
            res.insert(0,s.charAt(i));
        return res.toString();
    }
}

你可能感兴趣的:(逆序问题344、541、345、917、557)