344.反转字符串
编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。
不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。
示例 1:
输入:["h","e","l","l","o"]
输出:["o","l","l","e","h"]
示例 2:
输入:["H","a","n","n","a","h"]
输出:["h","a","n","n","a","H"]
思路:
双指针,一头一尾
class Solution {
public void reverseString(char[] s) {
int i = 0;
int j = s.length-1;
while(i < j){
char tmp = s[i];
s[i] = s[j];
s[j] = tmp;
i++;
j--;
}
}
}
541. 反转字符串II
给定一个字符串 s 和一个整数 k,从字符串开头算起, 每计数至 2k 个字符,就反转这 2k 个字符中的前 k 个字符。
如果剩余字符少于 k 个,则将剩余字符全部反转。
如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。
示例:
输入: s = "abcdefg", k = 2
输出: "bacdfeg"
思路:
这个一刷我没写出来,昨晚看了眼,觉得挺难,原以为自己还是写不出来的,但花了一小时磨磨蹭蹭慢慢竟然AC了,还是蛮有成就感的。
审题要清晰,我自己写的可能没有题解那么简介,但自认为可读性强。主要分为三种情况:
1、字符串长度小于2k但大于等于k
2、字符串长度小于k
3、字符串长度大于等于2k
分别对这三种情况进行讨论
class Solution {
public String reverseStr(String s, int k) {
//将字符串转为字符数组
char[] t = s.toCharArray();
//情况1:字符数组长度小于2k但是大于等于k
if(t.length < 2*k && t.length >= k){
int i = 0;
int j = k-1;
while(i < j){ //反转字符
char tmp = t[i];
t[i] = t[j];
t[j] = tmp;
i++;
j--;
}
//字符数组转为字符串,还可以用String.valueOf(t)
return new String(t);
//情况2:字符数组长度小于k
}else if(t.length < k){
int i = 0;
int j = t.length-1;
while(i < j){
char tmp = t[i];
t[i] = t[j];
t[j] = tmp;
i++;
j--;
}
return new String(t);
//情况3:字符数组长度大于2k
}else{
for(int i = 0; i < t.length; i += 2*k){
int n = i;
int j = i+k-1;
//判断加了k之后是否会超出字符数组长度
if(j < t.length){
while(n < j){
char tmp = t[n];
t[n] = t[j];
t[j] = tmp;
n++;
j--;
}
}else{
int m = t.length-1;
while(n < m){
char tmp = t[n];
t[n] = t[m];
t[m] = tmp;
n++;
m--;
}
}
}
return new String(t);
}
}
}
当然,题解更简洁了,下面是题解,题解先是将反转操作写成一个方法,然后再按照题目的要求优化代码。
class Solution {
public String reverseStr(String s, int k) {
char[] t = s.toCharArray();
for(int i = 0; i < t.length; i += 2*k){
if(i + k <= t.length){
reverse(t, i, i+k-1);
continue;
}else{
reverse(t, i, t.length-1);
}
}
return new String(t);
}
private void reverse(char[] t, int i, int j){
while(i < j){
char tmp = t[i];
t[i] = t[j];
t[j] = tmp;
i++;
j--;
}
}
}
题目:剑指Offer 05.替换空格
请实现一个函数,把字符串 s 中的每个空格替换成"%20"。
示例 1: 输入:s = "We are happy."
输出:"We%20are%20happy."
思路:
借用字符串当中的StringBuilder类,用于单线程字符串的缓冲区位置,一般用StringBuilder类会比StringBuffer快
class Solution {
public String replaceSpace(String s) {
if(s == null) return s;
StringBuffer sb = new StringBuffer();
for(int i = 0; i < s.length(); i++){
if(s.charAt(i) == ' '){
sb.append("%20");
}else{
sb.append(s.charAt(i));
}
}
return sb.toString();
}
}
151.翻转字符串里的单词
给定一个字符串,逐个翻转字符串中的每个单词。
示例 1:
输入: "the sky is blue"
输出: "blue is sky the"
示例 2:
输入: " hello world! "
输出: "world! hello"
解释: 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。
示例 3:
输入: "a good example"
输出: "example good a"
解释: 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。
思路:
先去除多余空格,再整体反转,最后再对每个单词反转。
但是知道原理是一回事儿,要把它写出来是另一回事儿,尝试了解如何利用StringBuilder类去写出对应方法。
class Solution {
public String reverseWords(String s) {
StringBuilder sb = removeSpace(s);
reverse(sb,0,sb.length()-1);
reverseEachWord(sb);
return sb.toString();
}
private void reverse(StringBuilder sb, int start, int end){
while(start < end){
char tmp = sb.charAt(start);
sb.setCharAt(start, sb.charAt(end));
sb.setCharAt(end, tmp);
start++;
end--;
}
}
private StringBuilder removeSpace(String s){
int start = 0;
int end = s.length()-1;
while(s.charAt(start) == ' ') start++;
while(s.charAt(end) == ' ') end--;
StringBuilder sb = new StringBuilder();
while(start <= end){
char c = s.charAt(start);
if(c != ' ' || sb.charAt(sb.length() - 1) != ' '){
sb.append(c);
}
start++;
}
return sb;
}
private void reverseEachWord(StringBuilder sb){
int start = 0;
int end = 1;
int n = sb.length();
while(start < n){
while(end < n && sb.charAt(end) != ' '){
end++;
}
reverse(sb,start,end-1);
start = end+1;
end = start+1;
}
}
}
题目:剑指Offer58-II.左旋转字符串
字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。
示例 1:
输入: s = "abcdefg", k = 2
输出: "cdefgab"
示例 2:
输入: s = "lrloseumgh", k = 6
输出: "umghlrlose"
限制:
1 <= k < s.length <= 10000
思路:
新建StringBuilder对象,将从k到结尾的字符先添加,再添加0-k的字符
class Solution {
public String reverseLeftWords(String s, int k) {
StringBuilder sb = new StringBuilder();
for(int i = k; i < s.length(); i++){
sb.append(s.charAt(i));
}
for(int j = 0; j < k; j++){
sb.append(s.charAt(j));
}
return sb.toString();
}
}
题解是先反转0到k-1的字符串,再反转k到len-1的字符串,最后整体反转,也能达到效果。但感觉我这个更简单一些。
总计花了3.5h