Leetcode 344.反转字符串
题目链接
思路:利用两个指针交换前后对元素,这里有一个异或对方法,也比较简单,下面直接看代码。
代码:
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;
// left++;
// right--;
// }
// 方法二
//首先 ^是位异或运算,对应的二进制位同为0或同为1 结果为0。
//比如 a = 2 b = 1 对应的二进制为a = 10 b = 01 ,^异或操作
//所以 a ^= b 即 a = a^b 也就是 10^01 = 11 a变成11
//b ^= a 即 b = b^a 也就是 01^11= 10 b变成 10 即 b = b^(a^b) = a
//a ^= b 即 a = a^b 也就是 11^10 = 01 a变为01 即 a = (a^b)^b = b
//a和b完成交换。
int left = 0;
int right = s.length - 1;
while (left < right) {
// a ^= b 即 a = a^b 也就是 10^01 = 11 a变成11
s[left] ^= s[right];
// b ^= a 即 b = b^a 也就是 01^11= 10 b变成 10 即 b = b^(a^b) = a
s[right] ^= s[left];
// a ^= b 即 a = a^b 也就是 11^10 = 01 a变为01 即 a = (a^b)^b = b
s[left] ^= s[right];
left++;
right--;
}
}
}
Leetcode 541. 反转字符串II
题目链接
思路:直接按题意进行模拟:反转每个下标从2k的倍数开始的、长度为k的子串,若该子串长度不足k,则反转整个子串。
代码:
class Solution {
public String reverseStr(String s, int k) {
int n = s.length();
char[] arr = s.toCharArray();
for (int i = 0; i < n; i += 2 * k) {
// 反转每个下标从2k的倍数开始的、长度为k的子串,若该子串长度不足k,则反转整个子串。
reverse(arr, i, Math.min(i + k, n) - 1);
}
return new String(arr);
}
private void reverse(char[] arr, int left, int right) {
while (left < right) {
arr[left] ^= arr[right];
arr[right] ^= arr[left];
arr[left] ^= arr[right];
left++;
right--;
}
}
}
Leetcode 剑指Offer 05.替换空格
题目链接
思路:双指针法
代码:
class Solution {
public String replaceSpace(String s) {
if (s == null || s.length() == 0) {
return s;
}
// 扩充空间,空格数量x2
StringBuilder sb = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == ' ') {
sb.append(" ");
}
}
// 若是没有空格,则直接返回
if (sb.length() == 0) {
return s;
}
// 有空格的情况,定义两个指针
// 定义左指针,指向原始字符串最后一个位置
int left = s.length() - 1;
// 扩充字符串s的大小,也就是每个空格替换成"%20"之后的大小
s += sb.toString();
// 定义右指针,指向扩展后新字符串的最后一个位置
int right = s.length() - 1;
char[] chars = s.toCharArray();
while (left >= 0) {
// 从后往前填充
if (chars[left] == ' ') {
chars[right--] = '0';
chars[right--] = '2';
chars[right] = '%';
} else {
chars[right] = chars[left];
}
left--;
right--;
}
return new String(chars);
}
}
时间复杂度:O(n)
空间复杂度:O(n),使用StringBuilder开辟了新空间。
Leetcode 151.翻转字符串里的单词
题目链接
思路:
- 去除首尾以及中间多余空格
- 反转整个字符串
- 反转各个单词
代码:
class Solution {
/**
* 1.去除首尾以及中间多余空格
* 2.反转整个字符串
* 3.反转各个单词
*/
public String reverseWords(String s) {
// 1.去除首尾以及中间多余空格
StringBuilder sb = removeSpace(s);
// 2.反转整个字符串
reverseString(sb, 0, sb.length() - 1);
// 3.反转各个单词
reverseEachWord(sb);
return sb.toString();
}
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);
// 这里指如果sb的末尾已经是空格了,如果还有空格,则不加入空格
if (c != ' ' || sb.charAt(sb.length() - 1) != ' ') {
sb.append(c);
}
start++;
}
return sb;
}
private void reverseString(StringBuilder sb, int start, int end) {
while (start < end) {
char temp = sb.charAt(start);
sb.setCharAt(start, sb.charAt(end));
sb.setCharAt(end, temp);
start++;
end--;
}
}
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++;
}
reverseString(sb, start, end - 1);
start = end + 1;
end = start + 1;
}
}
}
Leetcode 剑指Offer58-II.左旋转字符串
题目链接
思路:先整个字符串反转,再反转前面的,最后反转后面n个
代码:
class Solution {
public String reverseLeftWords(String s, int n) {
// 用原始数组来进行操作,使其空间复杂度降为O(1)
char[] chars = s.toCharArray();
// 1.先反转整个字串
reverse(chars, 0, chars.length - 1);
// 2.再反转前面的
reverse(chars, 0, chars.length - 1 - n);
// 3.最后反转后面n个
reverse(chars, chars.length - n, chars.length - 1);
return new String(chars);
}
public void reverse(char[] chars, int left, int right) {
while (left < right) {
chars[left] ^= chars[right];
chars[right] ^= chars[left];
chars[left] ^= chars[right];
left++;
right--;
}
}
}