文档讲解:代码随想录 (programmercarl.com)
视频讲解:字符串基础操作! | LeetCode:344.反转字符串_哔哩哔哩_bilibili
状态:
344. 反转字符串 - 力扣(LeetCode)
简单介绍下这里的^运算符
运算规则
0 ^ 0 = 0
1 ^ 1 = 0
0 ^ 1 = 1
1 ^ 0 = 1
'a'的补码:01100001
'b'的补码:01100010
'a' ^ 'b' = 00000011
'a' ^ 'b' ^ 'b' = 01100001 = 'a'
'a' ^ 'b' ^ 'a' = 01100010 = 'b'
// 时间复杂度O(n)
// 空间复杂度O(1)
class Solution {
public void reverseString(char[] s) {
int left = 0;
int right = s.length - 1;
while(left < right) {
s[left] ^= s[right];
s[right] ^= s[left];
s[left++] ^= s[right--];
}
}
}
// 这个代码中的交换可能更容易理解
// 时间复杂度O(n)
// 空间复杂度O(1)
class Solution {
public void reverseString(char[] s) {
int left = 0;
int right = s.length - 1;
while(left < right) {
char temp = s[left];
s[left++] = s[right];
s[right--] = temp;
}
}
}
541. 反转字符串 II - 力扣(LeetCode)
自己的思路比较乱,直接放示例代码。
// 时间复杂度O(n)
// 空间复杂度O(1)
class Solution {
public String reverseStr(String s, int k) {
char[] arr = s.toCharArray();
// length必须先存起来,不然会报错
int length = arr.length;
int start = 0;
while(start < length) {
int left = start;
int right = Math.min(start + k - 1, length - 1);
while(left < right) {
arr[left] ^= arr[right];
arr[right] ^= arr[left];
arr[left++] ^= arr[right--];
}
start += (2 * k);
}
return new String(arr);
}
}
// 时间复杂度O(n)
// 空间复杂度O(1)
class Solution {
public String reverseStr(String s, int k) {
StringBuffer res = new StringBuffer();
int length = s.length();
int start = 0;
while(start < length) {
StringBuffer temp = new StringBuffer();
int firstK = Math.min(start + k, length);
int secondK = Math.min(start + 2 * k, length);
// 保存start到start + k之间数据反转后的数据
temp.append(s.substring(start, firstK));
res.append(temp.reverse());
// 保存start + k到start + 2 * k之间的数据
if(firstK < secondK)
res.append(s.substring(firstK, secondK));
start += (2 * k);
}
return new String(res);
}
}
剑指Offer 05.替换空格
由于力扣上没有这题,我把题目复制下来
请实现一个函数,把字符串 s 中的每个空格替换成"%20"。
示例 1: 输入:s = "We are happy."
输出:"We%20are%20happy."
这道题目的可以用双指针的办法来做,作为一个数组填充类问题,在扩充数组后,采用从后向前填充的方式。
public String replaceSpace(String s) {
if(s == null || s.length == 0)return s;
StringBuilder spa = new StringBuilder();
for(int i = 0; i < s.length(); i++) {
if(s.charAt(i) == " ")spa.append(" "); // 统计空格的数量并确定要扩充多少
}
if(spa.length == 0)return s;
int fast = s.length - 1; // 快指针
s += spa; // 扩充
char[] res = s.toCharArray();
int slow = res.length - 1; // 慢指针
while(fast >= 0) {
if(res[fast] == ' ') {
res[slow--] = '0';
res[slow--] = '2';
res[slow] = '%';
} else res[slow] = res[fast];
fast--;
slow--;
}
return new String(res);
}
// 巨麻烦的一种写法
class Solution {
public String reverseWords(String s) {
StringBuilder str = removeSpace(s);
reverseAll(str);
reverseEachWord(str);
return new String(str);
}
// 去掉句中多余的空格
public StringBuilder removeSpace(String s) {
StringBuilder str = new StringBuilder();
int cur = 0;
int end = s.length();
// 去掉句首的空格
while(cur < s.length() && s.charAt(cur) == ' ')cur++;
// 去掉句末的空格
while(end > 0 && s.charAt(end - 1) == ' ')end--;
// 去掉句中多余的空格
while(cur < end) {
if (cur != 0 && s.charAt(cur) == s.charAt(cur - 1)
&& s.charAt(cur) == ' ') {
cur++;
continue;
}
str.append(s.charAt(cur));
cur++;
}
return str;
}
// 将整句左右倒置
public void reverseAll(StringBuilder str) {
int left = 0;
int right = str.length() - 1;
while(left < right) {
char temp = str.charAt(left);
str.setCharAt(left, str.charAt(right));
str.setCharAt(right, temp);
left++;
right--;
}
}
// 将每个单词倒置回来
public void reverseEachWord(StringBuilder s) {
int left = 0;
int end = 0;
while(end < s.length()) {
if(s.charAt(end) == ' ' || end == s.length() - 1) {
int right = end == s.length() - 1 ? end : end - 1;
while(left < right) {
char temp = s.charAt(left);
s.setCharAt(left, s.charAt(right));
s.setCharAt(right, temp);
left++;
right--;
}
left = end + 1;
}
end++;
}
}
}
// 简单明白的做法
class Solution {
public String reverseWords(String s) {
char[] arr = s.toCharArray();
char[] res = new char[arr.length + 1];
int num = 0;
int i = arr.length - 1;
while(i >= 0) {
while(i >= 0 && arr[i] == ' ')i--;
int right = i;
while(i >= 0 && arr[i] != ' ')i--;
for(int j = i + 1; j <= right; j++) {
res[num++] = arr[j];
if(j == right)res[num++] = ' ';
}
}
return new String(res, 0, num - 1);
}
}
剑指Offer58 左旋转字符串
LCR 182. 动态口令 - 力扣(LeetCode):题目比较类似。
class Solution {
public String dynamicPassword(String password, int target) {
char[] res = password.toCharArray();
reverse(res, 0, target - 1);
reverse(res, target, res.length - 1);
reverse(res, 0, res.length - 1);
return new String(res);
}
public void reverse(char[] password, int start, int end) {
while(start < end) {
char temp = password[start];
password[start++] = password[end];
password[end--] = temp;
}
}
}
心得: 耗时很久,非常痛苦,主要还是倒数第二题