344.反转字符串
编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。
不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
示例 1:
输入:s = ["h","e","l","l","o"]
输出:["o","l","l","e","h"]
示例 2:
输入:s = ["H","a","n","n","a","h"]
输出:["h","a","n","n","a","H"]
public void reverseString(char[] s) {
int left = 0;
int right = s.length - 1;
while(left <= right) {
char t = s[left];
s[left] = s[right];
s[right] = t;
left++;
right--;
}
}
}
这道题的话还是很简单的,就是双指针交换就可以了,不过也有更加优雅的写法~~下面会介绍的。
541. 反转字符串II
给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。
如果剩余字符少于 k 个,则将剩余字符全部反转。
如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。
示例 1:
输入:s = "abcdefg", k = 2
输出:"bacdfeg"
示例 2:
输入:s = "abcd", k = 2
输出:"bacd"
class Solution {
public String reverseStr(String s, int k) {
char[] str = s.toCharArray();
for(int i = 0; i < s.length(); i += 2 * k) {
int start = i;
int end = Math.min(s.length() - 1, start + k - 1);
while(start < end) {
str[start] ^= str[end];
str[end] ^= str[start];
str[start] ^= str[end];
start++;
end--;
}
}
return new String(str);
}
}
首先这里对于数组元素交换的操作是使用异或操作符^的,然后让i每次的循环中加上2k,分别找到终点与起点,进行反转。
剑指Offer 05.替换空格
请实现一个函数,把字符串 s 中的每个空格替换成"%20"。
示例 1:
输入:s = "We are happy."
输出:"We%20are%20happy."
class Solution {
public String replaceSpace(String s) {
if(s == null || s.length() == 0) {
return "";
}
StringBuffer str = new StringBuffer();
for(int i = 0; i < s.length(); i++) {
if(s.charAt(i) == ' ') {
str.append(" ");
}
}
if(str.length() == 0) {
return s;
}
int left = s.length() - 1;
s += str.toString();
int right = s.length() - 1;
char[] c = s.toCharArray();
while(left >= 0) {
if(c[left] == ' ') {
c[right--] = '0';
c[right--] = '2';
c[right--] = '%';
left--;
}else {
c[right--] = c[left--];
}
}
return new String(c);
}
}
这里是先对字符串进行了扩容,然后从后往前进行填充,left是指向原来的字符串,right是指向新的字符串,如果left指到了‘ ’则在right指针处写入“%20”,之所以要从后往前写,主要是因为,如果从前往后写的话要对数组进行位移操作,比较麻烦。
151.翻转字符串里的单词
给你一个字符串 s ,请你反转字符串中 单词 的顺序。
单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。
返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。
注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。
示例 1:
输入:s = "the sky is blue"
输出:"blue is sky the"
示例 2:
输入:s = " hello world "
输出:"world hello"
解释:反转后的字符串中不能存在前导空格和尾随空格。
示例 3:
输入:s = "a good example"
输出:"example good a"
解释:如果两个单词间有多余的空格,反转后的字符串需要将单词间的空格减少到仅有一个。
class Solution {
public String reverseWords(String s) {
if(s == null || s.length() == 0) {
return "";
}
char[] chars = s.toCharArray();
int slow = 0;
for(int fast = 0; fast < chars.length; fast++) {
if(chars[fast] != ' ') {
if(slow != 0) {
chars[slow++] = ' ';
}
while(fast < chars.length && chars[fast] != ' ') {
chars[slow++] = chars[fast++];
}
}
}
char[] newChars = new char[slow];
System.arraycopy(chars, 0, newChars, 0, slow);
reverse(newChars, 0, newChars.length - 1);
int left = 0;
for(int i = 0; i < newChars.length; i++) {
if(newChars[i] != ' ' && i != newChars.length - 1) {
continue;
}
if(i == newChars.length - 1) i++;
reverse(newChars, left, i - 1);
left = i + 1;
}
return new String(newChars);
}
private 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--;
}
}
}
这道题是相当的麻烦,不过大方向上还是先对大字符串中进行空格的剔除,然后对整体进行反转,然后再对字符串中存在的单词进行反转。不过在对空格进行剔除操作的时候,要注意在单词间留下一个空格,也就是说在fast指针已经读完一个单词的时候,slow指针处加上一个空格。
剑指Offer58-II.左旋转字符串
字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。
示例 1:
输入: s = "abcdefg", k = 2
输出: "cdefgab"
示例 2:
输入: s = "lrloseumgh", k = 6
输出: "umghlrlose"
很舒服的一道题,可以先创建一个数组,先把原字符串中下标为n到length-1的赋入,然后再写入0到n的字符,不过如果要求空间为O(1)可以试试这种写法:
class Solution {
public String reverseLeftWords(String s, int n) {
char[] chars = s.toCharArray();
reverse(chars, 0, n - 1);
reverse(chars, n, chars.length - 1);
reverse(chars, 0, chars.length - 1);
return new String(chars);
}
private 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--;
}
}
}
先对0到n的字符串进行反转,再对后续的进行反转,最后对整个字符串进行反转,就是我们所需的答案。