344.反转字符串
思路:
双指针,从char[]两端出发,交换字符。
代码:
class Solution {
public void reverseString(char[] s) {
for(int i = 0, j = s.length - 1; i < j; i++, j--){
s[i] ^= s[j];
s[j] ^= s[i];
s[i] ^= s[j];
}
}
}
需要注意的点:
1、学会用位运算交换的方法。
541. 反转字符串II
思路:
代码:
class Solution {
public String reverseStr(String s, int k) {
//string转化为char[]方便修改
char[] c = s.toCharArray();
for(int i = 0; i < c.length; i += 2 * k){
//如果剩余字符少于k,全部反转
reverse(c, i, Math.min(c.length - 1, i + k - 1));
}
return new String(c);
}
private void reverse(char[] c, int start, int end){
for(int i = start, j = end; i < j; i++, j--){
c[i] ^= c[j];
c[j] ^= c[i];
c[i] ^= c[j];
}
}
}
需要注意的点:
剑指Offer 05.替换空格
Stringbuilder:深入理解String、StringBuffer和StringBuilder_有头发的代码匠的博客-CSDN博客_stringbuilder内存结构
思路:
主要学会用双指针,无需额外空间。
在原字符串后加上2倍其空格数的空格,成为需要返回新字符串,用left指针指向原字符串的结尾,right指向新字符串的结尾,当遇到空格就补充‘20%’,从后向前更新两个指针,直至字符串开始(都是在转化成char[] 的基础上进行的)
代码:
1:新建数组存储
class Solution {
public String replaceSpace(String s) {
StringBuilder res = new StringBuilder();
for(int i = 0; i < s.length(); i++){
if(s.charAt(i) != ' '){
res.append(s.charAt(i));
}else{
res.append("%20");
}
}
return res.toString();
}
}
2:双指针更新
class Solution {
public String replaceSpace(String s) {
if(s == null || s.length() == 0){
return s;
}
StringBuilder str = new StringBuilder();
//str用于扩容s
for(int i = 0; i < s.length(); i++){
if(s.charAt(i) == ' '){
str.append(" ");
}
}
//如果没有空格,直接返回s
if(str.length() == 0){
return s;
}
int left = s.length() - 1;
s += str.toString();
int right = s.length() - 1;
char[] c = s.toCharArray();
while(right >= 0){
if(c[left] == ' '){
c[right--] = '0';
c[right--] = '2';
c[right] = '%';
}else{
c[right] = c[left];
}
left--;
right--;
}
return new String(c);
}
}
需要注意的点:
1、原字符串每有一个空格需要增加的空格数为2,而不是3(因为已经有一个空格)。
2、修改字符串(s)中的值,先转成char[](s.toCharArray()),再修改,最后转成string(String(char[] c))。
151.翻转字符串里的单词
思路:
见代码。
代码:
class Solution {
public String reverseWords(String s) {
char[] c = s.toCharArray();
//整个字符串反转
reverse(c, 0, c.length - 1);
int k = 0;
for(int i = 0; i < c.length; i++){
if(c[i] == ' '){
continue;
}
int start = i;
//此处尽管在大循环内,
//但只能保证i进入此循环时是<c.length的,
//不能保证i++之后还在此范围内
while(i < c.length && c[i] != ' '){
i++;
}
int end = i - 1;
//反转找到的单词
reverse(c, start, end);
//向前移位
for(int j = start; j < i;j++){
c[k++] = c[j];
}
//每个单词后加一个空格
if(k < c.length){
c[k++] = ' ';
}
}
return new String(c, 0, c[k - 1] != ' ' ? k : k - 1);
}
private void reverse(char[] c, int start, int end){
for(int i = start, j = end; i < j; i++, j--){
c[i] ^= c[j];
c[j] ^= c[i];
c[i] ^= c[j];
}
}
}
需要注意的点:
1、注意所有下标都不能超过字符串的长度。
2、最后可能出现多余空格,注意截取。
剑指Offer58-II.左旋转字符串
思路:
见代码注释。
代码:
class Solution {
public String reverseLeftWords(String s, int n) {
char[] c = s.toCharArray();
//分为三步:1、反转前n个字符;2、反转其余字符;3、反转整个字符串
reverse(c, 0, n - 1);
reverse(c, n, c.length - 1);
reverse(c, 0, c.length - 1);
return new String(c);
}
private void reverse(char[] c, int start, int end){
for(int i = start, j = end; i < j; i++, j--){
c[i] ^= c[j];
c[j] ^= c[i];
c[i] ^= c[j];
}
}
}