> 文档中心 > 【攻克剑指offer】第2天《替换空格》

【攻克剑指offer】第2天《替换空格》

替换空格


题目描述: 💦
在这里插入图片描述
👉题目链接👈

解法一、利用字符串中现有的方法

简单做一下java的String函数笔记:
public String replaceAll(String regex,String replacement)
用给定的替换替换与给定的regular expression匹配的此字符串的每个子字符串
参数
regex - 要匹配此字符串的正则表达式
replacement - 要替换每个匹配的字符串

public String replace(CharSequence target,CharSequence replacement)
将与字面目标序列匹配的字符串的每个子字符串替换为指定的字面替换序列
替换从字符串开始到结束,例如,在字符串“aaa”中用“b”替换“aa”将导致“ba”而不是“ab”。
参数
target - 要替换的char值序列
replacement - char值的替换顺序

代码如下 👇

 class Solution { public String replaceSpace(String s) {     return s.replace(" ","%20"); }    }
——☀️★☼☻🥛🍽️☻☼★☕*.——

解法二、使用StringBuilder

首先得先明白String、StringBuffer、StringBuilder的区别:

StringBuffer代表一个字符序列可变的字符串,当一个StringBuffer被创建以后,通过StringBuffer提供的append()、insert()、reverse()、setCharAt()、setLength()等方法可以改变这个字符串对象的字符序列。一旦通过StringBuffer生成了最终想要的字符串,就可以调用它的toString()方法将其转换为一个String对象

StringBuilder也代表可变字符串对象。实际上,StringBuilder和StringBuffer基本相似,两个类的构造器和方法也基本相同。不同的是:StringBuffer是线程安全的,而StringBuilder则没有实现线程安全功能,所以性能略高
所以有StringBuilder,我们就可以在一次for循环中直接判断是否为空格然后直接操作字符串。
append():将各种数据类型变量的字符串形式追加到当前序列中

想了解更多更详细的String、StringBuffer与StringBuilder的区别点击此处👉详细解释👈

代码如下👇

class Solution {public String replaceSpace(String s) { StringBuilder sb = new StringBuilder(); //初始化一个 StringBuilder 实例 sb //遍历字符串 s 的每个字符,我这里用的for-each循环既简便又可以避免循环条件和更新语句写错 //for(数据类型 变量名:集合对象名)     for (char c : s.toCharArray()) {   //==for(int i=0;i<s.length();i++) if (c == ' ') sb.append("%20");  //1.当遍历到非空字符的时候,直接将字符 append 到 sb 中    else sb.append(c);    //2.如果遍历到的是空字符,那么将 %20 append 到 sb 中      }   return sb.toString();  //3.返回 sb.toString}}

以上算法实现的复杂度分析:

  • 时间复杂度是: O(n)
  • 空间复杂度是 : O(n)
——☀️★☼☻🥛🍽️☻☼★☕*.——

解法三、数组

上种解法使用StringBuilde其实它本质上是一个 char 类型的动态数组:
当初始化 StringBuilder 的时候,会初始化一个固定长度的 char 类型的数组
当往 StringBuilder 中 append 数据的时候,其实就是往 char 类型的数组最后追加数据那么,当追加的数据的个数超过了数组的大小的时候,就需要对 char 类型的数据进行扩容了,所以这里的扩容还是有点性能损耗的
,既然都是数组那我们当然可以使用静态数组来解决问题了,从而可以消除数组动态扩容带来的性能损耗。

思路分析: 💫

  1. 我们要定义一个数组,但是不知长度,所以就设为n
  2. 我们知道一个“空格”可以转换为“%20”,但是又不知道数组里有多少个空格,但是知道是1:3的关系,所以我们可以极限处理设为3n
  3. 数组创建成功了,就下来就是判断了,我们使用双指针来判断
  4. 一个指针指向原数组索引为0的位置,另一个指针指向新开辟的静态数组索引为0的位置,然后遍历原数组,
  5. 如果不为空格则直接赋值给静态数组,为空格则将%20依次赋值到静态数组中

代码如下👇

class Solution {    public String replaceSpace(String s) { int n = s.length(); char[] newArr = new char[3 * n]; int j = 0; for (int i = 0; i < n; i++) {     char c = s.charAt(i);     if (c == ' ') {  newArr[j++] = '%';  newArr[j++] = '2';  newArr[j++] = '0';     } else {  newArr[j++] = c;     } } return new String(newArr, 0, j);    }}

但是你会发现如果原数组长度并不大呢,那么新开辟的空间不就浪费的很多吗
在这里插入图片描述
为了不浪费空间,所以我就需要事先知道数组长度
看下面图原数组一共有6个字符但是有2个空格,所以还需要格外的2*2=4个
所以只需找出原数组中有多少个空格就可以了
在这里插入图片描述

完善代码如下 👇

class Solution {  public String replaceSpace(String s) { int n = s.length(); int cnt = 0; for (char c : s.toCharArray()) {   //遍历数组     if (c == ' ') {   cnt++;    //计算出一共有多少个空格     } } char[] newArr = new char[n + 2 * cnt]; int j = 0; for (int i = 0; i < n; i++) {     char c = s.charAt(i);     if (c == ' ') {  newArr[j++] = '%';  newArr[j++] = '2';  newArr[j++] = '0';     } else {  newArr[j++] = c;     } } return new String(newArr, 0, j);    }}

以上算法实现的复杂度分析:

  • 时间复杂度是: O(n)
  • 空间复杂度是 : O(n)

🌈我的感受:

  我突然爱上了数组,太妙了,有遍历的题大多都少不了数组搭配,当然了有直接解法那肯定最简单,不过这String相关的知识还真是有点难记,这道题难度不大,但是对知识点的灵活应用还是比较高的。
【攻克剑指offer】第2天《替换空格》