344.反转字符串
思路
通过双指针对向遍历,交换两个指针指向的字符即可翻转字符串
注意:
通过异或运算法则,可以实现置换操作
解题思路
复杂度
时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( 1 ) O(1) O(1)
代码
Java
class Solution {
public void reverseString(char[] s) {
// 双指针对向遍历,交换
int left = 0;
int right = s.length - 1;
while (left < right) {
// 根据异或运算定律,进行交换操作
// https://blog.csdn.net/luoisK/article/details/127726559
s[left] ^= s[right];
s[right] ^= s[left];
s[left] ^= s[right];
left++;
right--;
}
}
}
541. 反转字符串II
思路
整体思路和上一道题一样,都是翻转字符
区别在于,这题对于翻转的位置有要求,概括为 每隔2k个反转前k个,尾数不够k个时候全部反转
解题思路
- 注意遍历的条件
- 注意边界条件
复杂度
时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( 1 ) O(1) O(1)
代码
Java
class Solution {
public String reverseStr(String s, int k) {
// 字符串先转字符数组
char[] chars = s.toCharArray();
// 题目的意思其实概括为 每隔2k个反转前k个,尾数不够k个时候全部反转
for (int i = 0; i < chars.length; i += 2 * k) {
int left = i;
int right = Math.min(chars.length - 1, i + k - 1);
while (left < right) {
chars[left] ^= chars[right];
chars[right] ^= chars[left];
chars[left] ^= chars[right];
left++;
right--;
}
}
return new String(chars);
}
}
剑指Offer 05.替换空格
思路
方法1:
遍历复制字符到另一个字符串中,碰到空格则替换
方法2:
双指针法。
先遍历获取有多少个空格,往数组添加额外的空格,然后用双指针从后往前遍历复制原字符,遇到空格则替换成%20
参考:https://programmercarl.com/%E5%89%91%E6%8C%87Offer05.%E6%9B%BF%E6%8D%A2%E7%A9%BA%E6%A0%BC.html#%E6%80%9D%E8%B7%AF
注意:这个方法在 Java 不好使,因为 String 是对象,其 char[]
字段不可变,因此这种解法的空间复杂度优势不存在
解题思路
复杂度
时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( n ) O(n) O(n)
代码
Java
class Solution {
public String replaceSpace(String s) {
// 遍历复制字符到另一个字符串中,碰到空格则替换,需要 n + m 的辅助空间
if (s == null) {
return null;
}
StringBuilder sb = new StringBuilder();
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.翻转字符串里的单词
思路
- 去除头尾和单词间多余的空格
- 翻转整个字符串
- 每个单词再翻转
解题思路
复杂度
时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( n ) O(n) O(n)
代码
Java
class Solution {
public String reverseWords(String s) {
// 去除头尾和单词间多余的空格
StringBuilder sb = removeBlank(s);
// 翻转则整个字符串
reverseString(sb, 0, sb.length() - 1);
// 每个单词再翻转
reverseWord(sb);
return sb.toString();
}
private StringBuilder removeBlank(String s) {
int left = 0;
int right = s.length() - 1;
// 去除头尾空格
while (s.charAt(left) == ' ') {
left++;
}
while (s.charAt(right) == ' ') {
right--;
}
// 去除单词间多于一个的空格
StringBuilder result = new StringBuilder();
while (left <= right) {
// 判断重复的通用方式,与前一个判断
if (s.charAt(left) != ' ' || s.charAt(left - 1) != ' ') {
result.append(s.charAt(left));
}
left++;
}
return result;
}
private void reverseString(StringBuilder sb, int left, int right) {
while (left < right) {
char temp = sb.charAt(left);
sb.setCharAt(left, sb.charAt(right));
sb.setCharAt(right, temp);
left++;
right--;
}
}
private void reverseWord(StringBuilder sb) {
// 单词的开始和结束
int start = 0;
int end = 1;
while (start < sb.length()) {
// 定位单词
while (end < sb.length() && sb.charAt(end) != ' ') {
end++;
}
// 交换
reverseString(sb, start, end - 1);
start = end + 1;
end = start + 1;
}
}
}
剑指Offer58-II.左旋转字符串
思路
- 翻转前n个
- 翻转剩余部分
- 整体再翻转
解题思路
复杂度
时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( n ) O(n) O(n)
代码
Java
class Solution {
public String reverseLeftWords(String s, int n) {
StringBuilder sb = new StringBuilder(s);
// 翻转前n个
reverseString(sb, 0, n - 1);
// 翻转剩余部分
reverseString(sb, n, s.length() - 1);
// 整体再翻转
reverseString(sb, 0, s.length() - 1);
return sb.toString();
}
private void reverseString(StringBuilder sb, int left, int right) {
while (left < right) {
char temp = sb.charAt(left);
sb.setCharAt(left, sb.charAt(right));
sb.setCharAt(right, temp);
left++;
right--;
}
}
}