Leetcode刷题字符串之反转字符串

一、反转字符串

1、问题描述

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

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

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

示例 1:

输入:[“h”,“e”,“l”,“l”,“o”]
输出:[“o”,“l”,“l”,“e”,“h”]

2、问题分析

直接两两交换字符即可。或者使用双指针。

3、代码

class Solution {
    public void reverseString(char[] s) {
        char temp;
        for(int i=0;i<(s.length/2);i++){
            temp = s[i];
            s[i] = s[s.length-1-i];
            s[s.length-1-i] = temp; 
        }
    }
}

二、反转字符串2

1、问题描述

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

示例:

输入: s = “abcdefg”, k = 2
输出: “bacdfeg”
要求:

该字符串只包含小写的英文字母。
给定字符串的长度和 k 在[1, 10000]范围内。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reverse-string-ii

2、问题分析

循环反转,设置一个指针cur,则[cur,cur+k)部分反转,[cur+k,cur+2k)保持不变。然后指针向右移动2k,同时剩余字符个数减少2k个。
调用字符串substring(start,end)方法截取字符串[start,end)部分,进行相应的操作,利用StringBuffer的reverse()方法反转。

3、代码

class Solution {
    public String reverseStr(String s, int k) {
        int l = s.length();
        int cur = 0;
        StringBuffer sb = new StringBuffer();
        while(l>=2*k){
            sb.append(new StringBuffer(s.substring(cur, cur+k)).reverse().append(s.substring(cur+k, cur+2*k)));
        //substring(start,end)   属于左闭右开实际上取到start...end-1
            l = l-2*k; //l剩余字符个数,因此要更新
            cur = cur+2*k; //指针也要更新
        }
        if(l<k){
            sb.append(new StringBuffer(s.substring(cur)).reverse());
        }else if(l<2*k){
            sb.append(new StringBuffer(s.substring(cur,cur+k)).reverse().append(s.substring(cur+k)));
        }
        return sb.toString();
    }
    
}

三、反转字符串中的元音字母

1、问题描述

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

示例 1:

输入: “hello”
输出: “holle”

2、问题分析

设置头尾指针,由于String类是不能改变的,所以要新建一个字符数组。最后再转换成字符串就可以了。

3、代码

import java.util.*;
class Solution {
    private final static Set<Character> set = new HashSet<>(Arrays.asList('A','E','I','O','U','a','e','i','o','u'));
    public String reverseVowels(String s) {
        /* 设置头尾指针 **/ 
        int head = 0;
        int tail = s.length()-1;
        /* 新建一个字符数组,因为String是不能变的 **/ 
        char[] rs = new char[tail+1];
        while(head<=tail){
            char ch = s.charAt(head);
            char ct = s.charAt(tail);
            if(!set.contains(ch)){
                rs[head] = ch;
                head++;
            }else if(!set.contains(ct)){
                rs[tail] = ct;
                tail--;
            }else{
                rs[head] = ct;
                head++;
                rs[tail] = ch;
                tail--;
            }
        }
        return new String(rs);
    }
}

四、仅仅反转字母

1、问题描述

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

示例 1:

输入:“ab-cd”
输出:“dc-ba”
示例 2:

输入:“a-bC-dEf-ghIj”
输出:“j-Ih-gfE-dCba”
示例 3:

输入:“Test1ng-Leet=code-Q!”
输出:“Qedo1ct-eeLg=ntse-T!”

提示:

S.length <= 100
33 <= S[i].ASCIIcode <= 122
S 中不包含 \ or "

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reverse-only-letters

2、问题分析

解法一:如题四方法,双指针遍历。
解法二:字母栈
将 s 中的所有字母单独存入栈中,所以出栈等价于对字母反序操作。(或者,可以用数组存储字母并反序数组。)
然后,遍历 s 的所有字符,如果是字母我们就选择栈顶元素输出。

3、代码

解法一:

class Solution {
    public String reverseOnlyLetters(String S) {
        int head = 0;
        int tail = S.length()-1;
        char[] rs = new char[tail+1]; //用来做首尾字母交换
        while(head<=tail){
            char c1 = S.charAt(head);
            char c2 = S.charAt(tail);
            if(!Character.isLetter(c1)){
                rs[head] = c1;
                head++;
            }else if(!Character.isLetter(c2)){
                rs[tail] = c2;
                tail--;
            }else{
                rs[head] = c2;
                head++;
                rs[tail] = c1;
                tail--;
            }
        }
        return new String(rs);
    }
}

解法二:

class Solution {
    public String reverseOnlyLetters(String S) {
        Stack<Character> letters = new Stack();
        for (char c: S.toCharArray())
            if (Character.isLetter(c))
                letters.push(c);

        StringBuilder ans = new StringBuilder();
        for (char c: S.toCharArray()) {
            if (Character.isLetter(c))
                ans.append(letters.pop());
            else
                ans.append(c);
        }

        return ans.toString();
    }
}

五、反转字符串的单词

1、问题描述

给定一个字符串,逐个翻转字符串中的每个单词。

示例 1:

输入: “the sky is blue”
输出: “blue is sky the”
示例 2:

输入: " hello world! "
输出: “world! hello”
解释: 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。
示例 3:

输入: “a good example”
输出: “example good a”
解释: 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。

说明:

无空格字符构成一个单词。
输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。
如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reverse-words-in-a-string

2、问题分析

本题难点在于,两个单词之间有多余空格的情况。利用字符串的split函数可以得到字符串数组。注意"a good example"返回的数组中含有空字符串,这就是其中的陷阱。新建一个StringBuffer,从字符串数组末尾开始添加到StringBuffer中,这样就能完成反转。最后把StringBuffer转换成String。

3、代码

class Solution {
    public String reverseWords(String s) {
        String[] words = s.split(" ");
        StringBuffer sb = new StringBuffer();
        for(int i=words.length-1;i>=0;i--){
            if(words[i].length()!=0){ //过滤数组字符串为空的情况
                sb.append(words[i]);
                sb.append(" ");
            }
        }
        return sb.toString().trim(); //trim去除字符串首尾空字符
    }
}

六、反转字符串的单词2

1、问题描述

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

示例 1:

输入: “Let’s take LeetCode contest”
输出: “s’teL ekat edoCteeL tsetnoc”
注意:在字符串中,每个单词由单个空格分隔,并且字符串中不会有任何额外的空格。

2、问题分析

利用字符串的split函数可以得到字符串数组。然后反转数组中的字符串即可。

3、代码

class Solution {
    public String reverseWords(String s) {
        String[] words = s.split(" ");
        StringBuffer sb = new StringBuffer();
        for(int i=0;i<words.length;i++){
            for(int j=words[i].length()-1;j>=0;j--){
                sb.append(words[i].charAt(j));
            }
            sb.append(" ");
        }
        return sb.toString().trim();
    }
}

当然可以使用StringBuffer的reverse()来反转。

	class Solution {
	    public String reverseWords(String s) {
	        String[] words = s.split(" ");
	        StringBuffer sb = new StringBuffer();
	        for(int i=0;i<words.length;i++){
	            StringBuffer temp = new StringBuffer();
	            temp.append(words[i]);
	            sb.append(temp.reverse()).append(" ");
	            
	        }
	        return sb.toString().trim();
	    }
	}

1、问题描述

2、问题分析

3、代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值