<String>逆序问题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

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<String> stack = new Stack();
        // for(char c : s.toCharArray())
        //     stack.push(""+c);
        Stack<Character> 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

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<j){
                char temp = arr[i];
                arr[i++] = arr[j];
                arr[j--] = temp;
            }
        }
        return new String(arr);
    }
}
image.png

345 Reverse Vowels of a String

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

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<end){
            while(start<end && !Character.isLetter(S.charAt(start)))
                start++;
            while(start<end && !Character.isLetter(S.charAt(end)))
                end--;
            if(start<end){
                char temp = arr[start];
                arr[start++] = arr[end];
                arr[end--] = temp;
            }
        }
        return new String(arr);
    }
}

解法二:利用栈

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

//使用栈
class Solution {
    public String reverseOnlyLetters(String S) {
        char[] arr = S.toCharArray();
        Stack<Character> 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

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();
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,539评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,594评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,871评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,963评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,984评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,763评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,468评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,357评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,850评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,002评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,144评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,823评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,483评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,026评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,150评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,415评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,092评论 2 355

推荐阅读更多精彩内容

  • 前言 最先接触编程的知识是在大学里面,大学里面学了一些基础的知识,c语言,java语言,单片机的汇编语言等;大学毕...
    oceanfive阅读 3,088评论 0 7
  • 一、基础知识:1、JVM、JRE和JDK的区别:JVM(Java Virtual Machine):java虚拟机...
    杀小贼阅读 2,383评论 0 4
  • String 的声明 由 JDK 中关于String的声明可以知道: 不同字符串可能共享同一个底层char数组,例...
    CodeKing2017阅读 1,638评论 1 2
  • 从网上复制的,看别人的比较全面,自己搬过来,方便以后查找。原链接:https://www.cnblogs.com/...
    lxtyp阅读 1,346评论 0 9
  • 十六月儿正长大 旧路新途老了吧 屠龙倚天都唱罢 雁南飞过雷峰塔
    板凳扫地僧阅读 74评论 0 0