知识点
字符串也是一种数组,在算法方面,二者类似。
Leetcode 344. 反转字符串
题目链接:344. 反转字符串
思路:
很基础的一道题。
解题:成功
代码实现
class Solution {
public void reverseString(char[] s) {
int n = s.length;
for(int i = 0; i < n / 2; i++){
char temp = s[i];
s[i] = s[n-1-i];
s[n-1-i] = temp;
}
}
}
Leetcode 541. 反转字符串 II
题目链接:541. 反转字符串 II
思路:
当需要固定规律一段一段去处理字符串的时候,要想想能否在for循环的表达式上做文章。
解题:成功
代码实现
class Solution {
public String reverseStr(String s, int k) {
char[] chs = s.toCharArray();
int n = chs.length;
for(int i = 0; i < n; i += 2 * k){
int left = i;
int right = i + k - 1;
if(right < n){
reverse(chs, left, right);
}
else{
reverse(chs, left, n-1);
}
}
// 或者 return new String(chs);
return String.valueOf(chs);
}
public void reverse(char[] chs, int left, int right){
while(left < right){
char temp = chs[left];
chs[left] = chs[right];
chs[right] = temp;
left++;
right--;
}
}
}
Leetcode 剑指 Offer 05. 替换空格
题目链接:剑指 Offer 05. 替换空格
思路:
对于线性数据结构,填充或者删除,后序处理会高效的多。
很多数组填充类的问题,都可以先预先给数组扩容成带填充后的大小,然后在从后向前进行操作。这么做有两个好处:
- 不用申请新数组。
- 从后向前填充元素,避免了从前向后填充元素时,每次添加元素都要将添加元素之后的所有元素向后移动的问题。
解题:成功
代码实现
方法一
class Solution {
public String replaceSpace(String s) {
StringBuilder sb = new StringBuilder();
for(int i = 0; i < s.length(); i++){
if(s.charAt(i) == ' '){
sb.append("%20");
continue;
}
sb.append(s.charAt(i));
}
return sb.toString();
}
}
方法二
class Solution {
public String replaceSpace(String s) {
if(s == null || s.length() == 0){
return s;
}
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 j = s.length() - 1;
s += sb.toString();
char[] chs = s.toCharArray();
int i = chs.length - 1;
for(; j < i; i--, j--){
if(chs[j] == ' '){
chs[i--] = '0';
chs[i--] = '2';
chs[i] = '%';
}
else{
chs[i] = chs[j];
}
}
return new String(chs);
}
}
Leetcode 151. 翻转字符串里的单词
题目链接:151. 翻转字符串里的单词
思路:
之前做过类似的题,但是忘记思路了。看了之前的笔记后,尝试写了一下,自己写的对于空格的相关处理逻辑写得很复杂。
空格处理部分和 27.移除元素 的逻辑是一样的,本题是移除空格,而 27.移除元素 就是移除元素。
解题:失败
代码实现
class Solution {
public String reverseWords(String s) {
char[] chs = s.toCharArray();
chs = removeExtraSpaces(chs);
reverseString(chs, 0, chs.length - 1);
reverseEachWord(chs);
return new String(chs);
}
public char[] removeExtraSpaces(char[] chs){
int slow = 0;
for(int fast = 0; fast < chs.length; fast++){
if(chs[fast] != ' '){
if(slow != 0){
chs[slow] = ' ';
slow++;
}
while(fast < chs.length && chs[fast] != ' '){
chs[slow] = chs[fast];
slow++;
fast++;
}
}
}
char[] newArr = new char[slow];
for(int i = 0; i < slow; i++){
newArr[i] = chs[i];
}
return newArr;
}
public void reverseString(char[] chs, int left, int right){
while(left < right){
char temp = chs[left];
chs[left] = chs[right];
chs[right] = temp;
left++;
right--;
}
}
public void reverseEachWord(char[] chs){
int start = 0;
for(int end = 0; end <= chs.length; end++){
if(end == chs.length || chs[end] == ' '){
reverseString(chs, start, end - 1);
start = end + 1;
}
}
}
}
Leetcode 剑指 Offer 58 - II. 左旋转字符串
思路:
之前看过一模一样的题(编程之美 2.17),但是没有自己写代码。忘记思路了。
解题:失败
代码实现
class Solution {
public String reverseLeftWords(String s, int n) {
char[] chs = s.toCharArray();
reverse(chs, 0, n-1);
reverse(chs, n, chs.length - 1);
reverse(chs, 0, chs.length - 1);
return new String(chs);
}
public void reverse(char[] chs, int left, int right){
while(left < right){
char temp = chs[left];
chs[left] = chs[right];
chs[right] = temp;
left++;
right--;
}
}
// 另一种反转字符串的写法
// 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--;
// }
// }
}
总结
后面两题还是有点难想的,只能加深印象,死记了:
- 在 151. 翻转字符串里的单词 (opens new window) 中,要对一句话里的单词顺序进行反转,先整体反转再局部反转是一个很妙的思路。
- 剑指 Offer 58 - II. 左旋转字符串 则是先局部反转再整体反转,与 151. 翻转字符串里的单词 (opens new window) 类似,但是也是一种新的思路。