代码随想录算法训练营第八天(字符串)| 344.反转字符串,541. 反转字符串II,剑指Offer 05.替换空格,151.翻转字符串里的单词,剑指Offer58-II.左旋转字符串
344.反转字符串
建议: 本题是字符串基础题目,就是考察 reverse 函数的实现,同时也明确一下 平时刷题什么时候用 库函数,什么时候 不用库函数
看到题目的第一想法:
双指针法:
设置两个指针,分别指向字符数组的开头和结尾,两两交换。
package com.second.day8;
public class ReverseString_344 {
public void reverseString(char[] s) {
int left = 0;
int right = s.length - 1;
while(left < right) {
char c = s[left];
s[left] = s[right];
s[right] = c;
left++;
right--;
}
}
}
看完代码随想录之后的想法:
easy
自己实现过程中遇到哪些困难:
easy
541. 反转字符串II
建议:本题又进阶了,自己先去独立做一做,然后在看题解,对代码技巧会有很深的体会。
看到题目的第一想法:
这道题,debug了半天最后才出来,有很多小细节处理的不到位。觉得这道题就是按照题目要求处理好遍历问题。
package com.second.day8;
public class ReverseStr_541 {
public String reverseStr(String s, int k) {
char[] str = s.toCharArray();
//字符长度小于等于k直接翻转返回
if(s.length() <= k) {
reverse(str, 0, str.length - 1);
return String.valueOf(str);
}
//count用来表示何时可以翻转
int count = 0;
for(int i = 0; i < str.length; i += k) {
if(count % 2 == 0) {
//当剩余字符小于等于k时,剩余部分进行翻转后返回
if(str.length - i <= k) {
reverse(str, i, str.length - 1);
return String.valueOf(str);
}
//count为0或偶数时进行翻转
reverse(str, i, i + k - 1);
}
count++;
}
return String.valueOf(str);
}
//翻转字符数组s序号为[left, right]的字符串
public void reverse(char s[], int left, int right) {
while (left < right) {
char c = s[left];
s[left] = s[right];
s[right] = c;
left++;
right--;
}
}
public static void main(String[] args) {
ReverseStr_541 demo = new ReverseStr_541();
demo.reverseStr("hyzqyljrnigxvdtneasepfahmtyhlohwxmkqcdf ehybknvdmfrfvtbsovjbdhevlfxpdaovjgunjql imjkfnqcqnajmebeddqsgl", 39);
}
}
看完代码随想录之后的想法:
好吧,是我输麻了。
卡哥代码太简洁了。
用java实现一下。
//翻转字符数组s序号为[left, right]的字符串
public void reverse(char s[], int left, int right) {
while (left < right) {
char c = s[left];
s[left] = s[right];
s[right] = c;
left++;
right--;
}
}
public String reverseStr1(String s, int k) {
char[] str = s.toCharArray();
for(int i = 0; i < str.length; i += 2 * k) {
// 1. 每隔 2k 个字符的前 k 个字符进行反转
// 2. 剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符
if(i + k < str.length) {
reverse(str, i, i + k - 1);
}
else {
// 3. 剩余字符少于 k 个,则将剩余字符全部反转。
reverse(str, i, str.length - 1);
}
}
return String.valueOf(str);
}
自己实现过程中遇到哪些困难:
字符数组转为字符串
String.valueOf(ch)
new String(ch)
剑指Offer 05.替换空格
建议:对于线性数据结构,填充或者删除,后序处理会高效的多。好好体会一下。
题目链接/文章讲解:
看到题目的第一想法:
1.遍历字符串统计其中有多少个空格
2.设置一个大小匹配的的字符数组str
3.遇到空格就到str中加入“%20”,否则加原字符
package com.second.day8;
public class ReplaceSpace_jz05 {
public String replaceSpace(String s) {
//遍历s统计有多少个空格
int count = 0;
for(int i = 0; i < s.length(); i++) {
if(s.charAt(i) == ' ')
count++;
}
//设置一个大小匹配的的字符数组str
char[] str = new char[s.length() + 2 * count];
int index = 0;
for(int i = 0; i < s.length(); i++) {
if(s.charAt(i) == ' ') {
str[index++] = '%';
str[index++] = '2';
str[index++] = '0';
}
else {
str[index++] = s.charAt(i);
}
}
return String.valueOf(str);
}
}
看完代码随想录之后的想法:
自己写的代码和卡哥最好的方法是一致的。牛逼plus!
自己实现过程中遇到哪些困难:
无
151.翻转字符串里的单词
建议:这道题目基本把 刚刚做过的字符串操作 都覆盖了,不过就算知道解题思路,本题代码并不容易写,要多练一练。
看到题目的第一想法:
从后往前推,记下每个单词的头和尾,然后添加入新的字符串中,只要不是首个单词,每个字符加个空格。
package com.second.day8;
public class ReverseWords_jz58 {
public String reverseWords(String s) {
//构造一个StringBuilder字符串构建器。
StringBuilder sb = new StringBuilder();
int left = s.length() - 1;
//去除前导空格
int start = 0;
while(start < left && s.charAt(start) == ' ') {
start++;
}
while(left >= start) {
//遇到空格就前进一位
while(left >= start && s.charAt(left) == ' ') {
left--;
}
//此时遇到了字符的末尾,记下来
int end = left;
while(left >= start && s.charAt(left) != ' ') {
left--;
}
//此时记入了字符的开头的第一个字符
int begin = left + 1;
//将该字符加入sb中
while(begin <= end) {
sb.append(s.charAt(begin));
begin++;
}
//若不是第一个字符就在最后还加一个空格
if(left + 1 != start)
sb.append(' ');
}
return sb.toString();
}
public static void main(String[] args) {
ReverseWords_jz58 demo = new ReverseWords_jz58();
demo.reverseWords("the sky is blue");
}
}
看完代码随想录之后的想法:
方法也太多了吧!!!看看卡哥怎么实现的,一个个看,不要放弃哦!
解法一:
class Solution {
public String reverseWords(String s) {
StringBuilder sb = removeSpace(s);
reverseString(sb, 0, sb.length() - 1);
reverseWord(sb);
return new String(sb);
}
//去除首尾以及中间多余空格
public StringBuilder removeSpace(String s) {
StringBuilder sb = new StringBuilder();
int start = 0;
int finish = s.length() - 1;
//去除前导空格
while(start < s.length() && s.charAt(start) == ' ')
start++;
//去除后导空格
while(finish >= start && s.charAt(finish) == ' ')
finish--;
//去除中间字符的多余空格
while(start <= finish) {
char c = s.charAt(start);
if(c == ' ' && s.charAt(start - 1) == ' ') {
start++;
continue;
}
sb.append(c);
start++;
}
return sb;
}
//反转整个字符串
public void reverseString(StringBuilder sb, int left, int right) {
while(left < right) {
char c = sb.charAt(left);
sb.setCharAt(left, sb.charAt(right));
sb.setCharAt(right, c);
left++;
right--;
}
}
//反转各个单词
public void reverseWord(StringBuilder sb) {
int start = 0;
while(start < sb.length()) {
int begin = start;
while(start < sb.length() && sb.charAt(start) != ' ')
start++;
if(start != sb.length() - 1)
reverseString(sb, begin, start - 1);
else
reverseString(sb, begin, start);
start++;
}
}
}
解法二:
和我自己想的差不多,俺真棒!
解法三,四和解法一二大同小异。
自己实现过程中遇到哪些困难:
StringBuilder和StringBuffer用的不太熟练。
剑指Offer58-II.左旋转字符串
建议:题解中的解法如果没接触过的话,应该会想不到
看到题目的第一想法:
1.构造一个StringBuilder字符串构建器sb。
2.将字符串s的[n,s.length-1]添加到sb中
3.将字符串s[0,n - 1]添加到sb中
package com.second.day8;
public class ReverseLeftWords_jz58_2 {
public String reverseLeftWords(String s, int n) {
//构造一个StringBuilder字符串构建器sb。
StringBuilder sb = new StringBuilder();
//将字符串s的[n,s.length-1]添加到sb中
for(int i = n; i < s.length(); i++) {
sb.append(s.charAt(i));
}
//将字符串s[0,n - 1]添加到sb中
for(int i = 0; i < n; i++) {
sb.append(s.charAt(i));
}
return sb.toString();
}
}
看完代码随想录之后的想法:
妙啊。
1.反转区间为前n的子串
2.反转区间为n到末尾的子串
3.反转整个字符串
自己实现过程中遇到哪些困难:
无
今日收获,记录一下自己的学习时长:
今天的题目难度对我来说还是比较适中的,都能够很快想到思路,然后AC出。加油,少年,坚持下去。
今天写了五个题:
344.反转字符串 , 541. 反转字符串II, 剑指Offer 05.替换空格 ,151.翻转字符串里的单词,剑指Offer58-II.左旋转字符串
代码:1.5h
博客:1.5h
努力是一种生活态度,与年龄无关。所以,无论什么时候,千万不可放纵自己,给自己找懒散和拖延的借口,对自己严格一点儿,时间长了,努力便成为一种心理习惯,一种生活方式!