一、反转字符串
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();
}
}