力扣每日一题
2390.从字符串中移除星号
给你一个包含若干星号 *
的字符串 s
。
在一步操作中,你可以:
- 选中
s
中的一个星号。 - 移除星号 左侧 最近的那个 非星号 字符,并移除该星号自身。
返回移除 所有 星号之后的字符串。
注意:
- 生成的输入保证总是可以执行题面中描述的操作。
- 可以证明结果字符串是唯一的。
示例 1:
输入:s = "leet**cod*e" 输出:"lecoe" 解释:从左到右执行移除操作: - 距离第 1 个星号最近的字符是 "leet**cod*e" 中的 't' ,s 变为 "lee*cod*e" 。 - 距离第 2 个星号最近的字符是 "lee*cod*e" 中的 'e' ,s 变为 "lecod*e" 。 - 距离第 3 个星号最近的字符是 "lecod*e" 中的 'd' ,s 变为 "lecoe" 。 不存在其他星号,返回 "lecoe" 。
示例 2:
输入:s = "erase*****" 输出:"" 解释:整个字符串都会被移除,所以返回空字符串。
提示:
1 <= s.length <= 105
s
由小写英文字母和星号*
组成s
可以执行上述操作
class Solution {
public String removeStars(String s) { // 定义一个方法 removeStars,用来移除字符串中被星号删除的字符
StringBuilder st = new StringBuilder(); // 使用 StringBuilder 来构建结果字符串
for(char i : s.toCharArray()){ // 遍历字符串 s,将其转化为字符数组
if(i == '*'){ // 如果当前字符是 '*'
st.deleteCharAt(st.length()-1); // 删除 StringBuilder 中最后一个字符
}
else{ // 如果当前字符不是 '*'
st.append(i); // 将当前字符添加到 StringBuilder 中
}
}
return st.toString(); // 将 StringBuilder 转换为字符串并返回
}
}
这道题真的不难,但是为什么要记录下来呢?因为字符串的处理对于我来说一直算是短板
我只是单纯的不会,菜只能多练
StringBuilder
是 Java 中用于创建和操作可变字符串的类。与StringBuffer
类似,它可以对字符串进行高效的修改和操作,但是StringBuilder
是非线程安全 的,适合单线程环境中使用。相比String
,StringBuilder
在频繁的字符串拼接、修改操作中性能更优。以下是
StringBuilder
的一些常用操作和方法:1. 构造方法
StringBuilder sb1 = new StringBuilder(); // 创建一个空的 StringBuilder StringBuilder sb2 = new StringBuilder("Hello"); // 创建一个初始化为 "Hello" 的 StringBuilder StringBuilder sb3 = new StringBuilder(50); // 创建一个具有 50 个字符容量的 StringBuilder
2.
append()
- 追加字符串将指定的内容追加到
StringBuilder
的末尾。StringBuilder sb = new StringBuilder("Hello"); sb.append(" World"); sb.append(123); // 支持追加其他类型的数据,如 int、float 等 System.out.println(sb.toString()); // 输出: Hello World123
3.
insert()
- 插入字符串在指定位置插入字符串或其他数据类型。
StringBuilder sb = new StringBuilder("Hello World"); sb.insert(6, "Java "); // 在索引 6 的位置插入 "Java " System.out.println(sb.toString()); // 输出: Hello Java World
4.
delete()
- 删除字符串删除指定范围内的字符。
StringBuilder sb = new StringBuilder("Hello Java World"); sb.delete(6, 11); // 删除索引 6 到 10 的字符 (不包括索引 11) System.out.println(sb.toString()); // 输出: Hello World
5.
deleteCharAt()
- 删除单个字符删除指定位置的字符。
StringBuilder sb = new StringBuilder("Hello World"); sb.replace(6, 11, "Java"); // 将索引 6 到 10 的字符替换为 "Java" System.out.println(sb.toString()); // 输出: Hello Java
6.
replace()
- 替换字符串替换指定范围内的字符为给定的字符串。
StringBuilder sb = new StringBuilder("Hello World"); sb.replace(6, 11, "Java"); // 将索引 6 到 10 的字符替换为 "Java" System.out.println(sb.toString()); // 输出: Hello Java
7.
reverse()
- 字符串反转将字符串内容反转。
StringBuilder sb = new StringBuilder("Hello"); sb.reverse(); System.out.println(sb.toString()); // 输出: olleH
8.
capacity()
- 获取容量StringBuilder sb = new StringBuilder("Hello"); System.out.println(sb.capacity()); // 输出当前容量,默认是 16 加上初始化字符串的长度
9.
ensureCapacity()
- 确保容量确保
StringBuilder
至少具有指定的容量,避免因扩容而导致性能下降。StringBuilder sb = new StringBuilder(); sb.ensureCapacity(50); // 确保 StringBuilder 至少具有 50 个字符的容量
10.
length()
- 获取长度返回
StringBuilder
当前包含的字符数(与容量不同)。StringBuilder sb = new StringBuilder("Hello"); System.out.println(sb.length()); // 输出: 5
11.
charAt()
- 获取指定位置的字符返回
StringBuilder
中指定索引处的字符。StringBuilder sb = new StringBuilder("Hello"); System.out.println(sb.charAt(1)); // 输出: e
12.
setCharAt()
- 设置指定位置的字符修改指定索引处的字符。
StringBuilder sb = new StringBuilder("Hello"); sb.setCharAt(1, 'a'); // 将索引 1 处的字符修改为 'a' System.out.println(sb.toString()); // 输出: Hallo
13.
substring()
- 提取子字符串返回从指定开始索引到结束索引之间的子字符串(结束索引不包括)。
StringBuilder sb = new StringBuilder("Hello World"); String sub = sb.substring(6, 11); // 提取从索引 6 到 10 的子字符串 System.out.println(sub); // 输出: World
14.
toString()
- 转换为字符串将
StringBuilder
对象转换为String
。StringBuilder sb = new StringBuilder("Hello"); String result = sb.toString(); // 将 StringBuilder 转换为字符串 System.out.println(result); // 输出: Hello
15.
trimToSize()
- 减少容量将
StringBuilder
的容量缩减到其当前内容的长度。StringBuilder sb = new StringBuilder(100); // 初始化容量为 100 sb.append("Hello"); sb.trimToSize(); // 将容量缩减为当前内容的长度,即 5
示例代码:综合操作
public class StringBuilderExample { public static void main(String[] args) { StringBuilder sb = new StringBuilder("Hello"); // 追加 sb.append(" World"); System.out.println("After append: " + sb.toString()); // 输出: Hello World // 插入 sb.insert(6, "Java "); System.out.println("After insert: " + sb.toString()); // 输出: Hello Java World // 删除 sb.delete(5, 10); System.out.println("After delete: " + sb.toString()); // 输出: Hello World // 替换 sb.replace(6, 11, "Everyone"); System.out.println("After replace: " + sb.toString()); // 输出: Hello Everyone // 反转 sb.reverse(); System.out.println("After reverse: " + sb.toString()); // 输出: enoyrevE olleH } }
总结
StringBuilder
是一个高效、灵活的工具,适合在单线程环境中对字符串进行频繁修改。它常用于字符串拼接、插入、删除、替换等操作,尤其是在构建大量字符串或处理大文本时,比直接使用String
效率更高。
.
StringJoiner
:
- 主要功能:
StringJoiner
是在 Java 8 中引入的,用于连接字符串,并且可以指定分隔符、前缀和后缀。- 线程安全性:
StringJoiner
是非线程安全的,所以不能在多线程环境中直接使用。- 典型用法:适合在需要连接多个字符串并使用分隔符的场景。
示例:
import java.util.StringJoiner; public class StringJoinerExample { public static void main(String[] args) { // 创建一个 StringJoiner,指定分隔符、前缀和后缀 StringJoiner joiner = new StringJoiner(", ", "[", "]"); // 添加元素 joiner.add("Alice"); joiner.add("Bob"); joiner.add("Charlie"); // 输出结果 System.out.println(joiner.toString()); // 输出: [Alice, Bob, Charlie] } }
- 解释:
StringJoiner
用于连接多个字符串,字符串之间使用,
作为分隔符,并且结果会被[]
包裹。2.
StringBuffer
:
- 主要功能:
StringBuffer
是一个可变的字符串序列,常用于字符串的拼接、修改等操作。与StringBuilder
类似,但它是线程安全的,因此适用于多线程环境。- 线程安全性:
StringBuffer
是线程安全的,因为它的所有方法都被synchronized
修饰。- 典型用法:适合在需要频繁修改字符串或在多线程环境中操作字符串的场景。
public class StringBufferExample { public static void main(String[] args) { // 创建一个 StringBuffer StringBuffer sb = new StringBuffer("Hello"); // 追加字符串 sb.append(" World"); // 插入字符串 sb.insert(6, "Java "); // 删除字符串的一部分 sb.delete(11, 16); // 输出结果 System.out.println(sb.toString()); // 输出: Hello Java World } }
- 解释:
StringBuffer
提供了各种操作字符串的方法,如append()
、insert()
、delete()
等,适合需要修改已有字符串的场景。3. 区别:
特性 StringJoiner
StringBuffer
主要用途 连接多个字符串,支持分隔符、前缀和后缀 操作和修改字符串,拼接、插入、删除等 线程安全性 非线程安全 线程安全 常见方法 add()
,toString()
append()
,insert()
,delete()
,replace()
引入版本 Java 8 Java 1.0 性能 比 StringBuffer
快,适合简单的字符串拼接线程安全开销较大,适合多线程环境 总结:
- 如果你需要连接多个字符串并使用分隔符(如逗号、空格等),那么
StringJoiner
是理想的选择。- 如果你需要在多线程环境下频繁修改字符串(例如拼接、删除等操作),那么
StringBuffer
更加合适。