文章目录
Day 8 第四章 字符串part01
- 今日任务
- 344.反转字符串; 541. 反转字符串II; 卡码网:54.替换数字; 151.翻转字符串里的单词; 卡码网:55.右旋转字符串
344.反转字符串
- 建议: 本题是字符串基础题目,就是考察 reverse 函数的实现,同时也明确一下 平时刷题什么时候用 库函数,什么时候 不用库函数
- 题目链接:https://leetcode.cn/problems/reverse-string/
- 视频讲解:https://www.bilibili.com/video/BV1fV4y17748/
- 文章讲解:https://programmercarl.com/0344.%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2.html
自己的思路(✅通过)
双指针不断往中间移动
public static void reverseString(char[] s) {
int left = 0;
int right = s.length - 1;
char temp;
while(left < right){
temp = s[left];
s[left] = s[right];
s[right] = temp;
left ++;
right --;
}
}
541. 反转字符串II
- 建议:本题又进阶了,自己先去独立做一做,然后在看题解,对代码技巧会有很深的体会。
- 题目链接:https://leetcode.cn/problems/reverse-string-ii/
- 视频讲解:https://www.bilibili.com/video/BV1dT411j7NN/
- 文章讲解:https://programmercarl.com/0541.%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2II.html
自己的思路(✅通过但用时太长)
先把s分成几个长度为2k的字符串,然后进行交换
public static String reverseStr(String s, int k) {
int count = s.length() / (k * 2) + 1;
String result = "";
String sn[] = new String[count];
for(int i = 0; i < count; i ++){
sn[i] = "";
}
for(int i = 0; i < s.length(); i ++){
sn[i / (k * 2)] = sn[i / (k * 2)] + s.charAt(i);
}
for(int i = 0; i < count; i ++){
sn[i] = reverseString(sn[i], k);
result = result + sn[i];
}
return result;
}
public static String reverseString(String s, int k) {
int left = 0;
int right;
if(s.length() < k) right = s.length() - 1;
else right = k - 1;
char temp;
char c[] = s.toCharArray();
while(left < right){
temp = c[left];
c[left] = c[right];
c[right] = temp;
left ++;
right --;
}
s = String.valueOf(c);
return s;
}
随想录思路
for循环内不要直接写i++,写成i+=2k,这样一次操作2k个字符就很方便
public String reverseStr(String s, int k) {
char[] ch = s.toCharArray();
// 1. 每隔 2k 个字符的前 k 个字符进行反转
for (int i = 0; i< ch.length; i += 2 * k) {
// 2. 剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符
if (i + k <= ch.length) {
reverse(ch, i, i + k -1);
continue;
}
// 3. 剩余字符少于 k 个,则将剩余字符全部反转
reverse(ch, i, ch.length - 1);
}
return new String(ch);
}
// 定义翻转函数
public void reverse(char[] ch, int i, int j) {
for (; i < j; i++, j--) {
char temp = ch[i];
ch[i] = ch[j];
ch[j] = temp;
}
}
卡码网:54.替换数字
- 建议:对于线性数据结构,填充或者删除,后序处理会高效的多。好好体会一下。
- 题目链接:https://kamacoder.com/problempage.php?pid=1064
- 文章讲解:https://programmercarl.com/kama54.%E6%9B%BF%E6%8D%A2%E6%95%B0%E5%AD%97.html
自己的思路(✅通过)
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String s = in.nextLine();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
if (Character.isDigit(s.charAt(i))) {
sb.append("number");
}else sb.append(s.charAt(i));
}
System.out.println(sb);
}
}
知识点
StringBuilder
类
String
& StringBuffer
& StringBuilder
- 当对字符串进行修改的时候,需要使用 StringBuffer 和 StringBuilder 类。
- 在使用 StringBuffer 类时,每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象,所以如果需要对字符串进行修改推荐使用 StringBuffer。
- 由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。
- 和 String 类不同的是,StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象。
StringBuilder
的方法
- 添加元素
StringBuilder append(Object obj):直接从尾部添加
StringBuilder insert(int offset, Object obj):从指定位置插入
void setCharAt(int index, Object obj):指定索引处的字符设置为ch
- 查询
char charAt(int index):返回char指定索引处的此序列中的值
String toString():返回表示此序列中数据的字符串
int indexOf(Object obj):返回指定子字符串第一次出现的字符串中的索引
int length(): 返回长度(字符数)
- 删除
StringBuilder delete(int start, int end):删除此序列的子字符串中的字符
StringBuilder deleteCharAt(int index):char按此顺序删除指定位置
- 替换
StringBuilder replace(int start, int end, String str):用指定的字符替换此序列的子字符串中的字符String
Character
类
转义序列
\t
:在文中该处插入一个tab键
\b
:在文中该处插入一个后退键
\n
:在文中该处换行
\r
:在文中该处插入回车
\f
:在文中该处插入换页符
\'
:在文中该处插入单引号
\"
:在文中该处插入双引号
\\
:在文中该处插入反斜杠
方法
isLetter()
是否是一个字母
isDigit()
是否是一个数字字符
isWhitespace()
是否是一个空白字符
isUpperCase()
是否是大写字母
isLowerCase()
是否是小写字母
toUpperCase()
指定字母的大写形式
toLowerCase
指定字母的小写形式
toString
返回字符的字符串形式,字符串的长度仅为1
151.翻转字符串里的单词
- 建议:这道题目基本把 刚刚做过的字符串操作 都覆盖了,不过就算知道解题思路,本题代码并不容易写,要多练一练。
- 题目链接:https://leetcode.cn/problems/reverse-words-in-a-string/
- 视频讲解:https://www.bilibili.com/video/BV1uT41177fX/
- 文章讲解:https://programmercarl.com/0151.%E7%BF%BB%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2%E9%87%8C%E7%9A%84%E5%8D%95%E8%AF%8D.html
- 参考视频:https://b23.tv/ZTZb0da
思路
代码
public static String reverseWords(String s) {
StringBuilder sb = new StringBuilder();
int left = 0;
int right = s.length() - 1;
int index;
while(s.charAt(left) == ' ') left ++;
//注意left可以等于right,因为有字符串只有一个字符的情况
while(left <= right){
while(s.charAt(right) == ' ') right --;
index = right;
//注意index移动的条件,index要大于0防止index-1越界
while(index > 0 && s.charAt(index - 1) != ' ') index --;
//向结果字符串中添加单词
for(int i = index; i <= right; i ++) sb.append(s.charAt(i));
//不是最后一个单词时要多添加一个空格
if(index != left) sb.append(" ");
//更新right的位置
right = index - 1;
}
return sb.toString();
}
卡码网:55.右旋转字符串
- 建议:题解中的解法如果没接触过的话,应该会想不到
- 题目链接:https://kamacoder.com/problempage.php?pid=1065
- 文章讲解:
https://programmercarl.com/kama55.%E5%8F%B3%E6%97%8B%E5%AD%97%E7%AC%A6%E4%B8%B2.html
自己的思路(✅通过)
import java.util.*;
class Main{
public static void main(String[] srg){
Scanner sc = new Scanner(System.in);
int k = sc.nextInt();
String s = sc.next();
//System.out.println(k+" "+s);
StringBuilder sb = new StringBuilder();
if(k < s.length()){
for(int i = s.length() - k; i < s.length(); i++){
sb.append(s.charAt(i));
}
for(int i = 0; i < s.length() - k; i++){
sb.append(s.charAt(i));
}
System.out.println(sb);
}else System.out.println(s);
}
}
随想录思路
- 把字符串分成两段:a b c d e | f g
- 先反转前段字符串,再反转后段字符串:e d c b a | g f
- 最后反转整个字符串:f g | a b c d e
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = Integer.parseInt(in.nextLine());
String s = in.nextLine();
int len = s.length(); //获取字符串长度
char[] chars = s.toCharArray();
reverseString(chars, 0, len - n - 1); //反转前一段字符串,此时的字符串首尾是0,len - n - 1
reverseString(chars, len - n, len - 1); //反转后一段字符串,此时的字符串首尾是len - n,len - 1
reverseString(chars, 0, len - 1); //反转整个字符串
System.out.println(chars);
}
public static void reverseString(char[] ch, int start, int end) {
//异或法反转字符串,参照题目 344.反转字符串的解释
while (start < end) {
ch[start] ^= ch[end];
ch[end] ^= ch[start];
ch[start] ^= ch[end];
start++;
end--;
}
}
}