• 剑指 Offer 05. 替换空格


    题目:https://leetcode-cn.com/problems/ti-huan-kong-ge-lcof/

    我的代码:

        public static String replaceSpace(String s) {
            if (s == "") return null;
            return s.replace(" ", "%20");
        }

    知识点:

    1、JAVA中替换字符的方法replace和replaceAll 区别:(https://www.cnblogs.com/shuilangyizu/p/6612240.html)

    • replace的参数是char和CharSequence,即可以支持字符的替换,也支持字符串的替换(CharSequence即字符串序列的意思,说白了也就是字符串);
    • replaceAll的参数是regex或者char,即基于规则表达式的替换,比如,可以通过replaceAll("\d", "*")把一个字符串所有的数字字符都换成星号;
    • 相同点是都是全部替换,即把源字符串中的某一字符或字符串全部换成指定的字符或字符串。
    • 如果只想替换第一次出现的,可以使用replaceFirst(),这个方法也是基于规则表达式的替换,但与replaceAll()不同的时,只替换第一次出现的字符串;
    • 另外,如果replaceAll()和replaceFirst()所用的参数据不是基于规则表达式的,则与replace()替换字符串的效果是一样的,即这两者也支持字符串的操作

    别人的解答:

    https://programmercarl.com/%E5%89%91%E6%8C%87Offer05.%E6%9B%BF%E6%8D%A2%E7%A9%BA%E6%A0%BC.html#%E5%85%B6%E4%BB%96%E8%AF%AD%E8%A8%80%E7%89%88%E6%9C%AC

    (C++)

    如果想把这道题目做到极致,就不要只用额外的辅助空间了!首先扩充数组到每个空格替换成"%20"之后的大小。然后从后向前替换空格,也就是双指针法,过程如下:i指向新长度的末尾,j指向旧长度的末尾。

     有同学问了,为什么要从后向前填充,从前向后填充不行么?

    从前向后填充就是O(n^2)的算法了,因为每次添加元素都要将添加元素之后的所有元素向后移动。
    其实很多数组填充类的问题,都可以先预先给数组扩容带填充后的大小,然后在从后向前进行操作。
    这么做有两个好处:
    不用申请新数组。从后向前填充元素,避免了从前先后填充元素要来的 每次添加元素都要将添加元素之后的所有元素向后移动。时间复杂度,空间复杂度均超过100%的用户。

    class Solution {
    public:
        string replaceSpace(string s) {
            int count = 0; // 统计空格的个数
            int sOldSize = s.size();
            for (int i = 0; i < s.size(); i++) {
                if (s[i] == ' ') {
                    count++;
                }
            }
            // 扩充字符串s的大小,也就是每个空格替换成"%20"之后的大小
            s.resize(s.size() + count * 2);
            int sNewSize = s.size();
            // 从后先前将空格替换为"%20"
            for (int i = sNewSize - 1, j = sOldSize - 1; j < i; i--, j--) {
                if (s[j] != ' ') {
                    s[i] = s[j];
                } else {
                    s[i] = '0';
                    s[i - 1] = '2';
                    s[i - 2] = '%';
                    i -= 2;
                }
            }
            return s;
        }
    };

    java:

    //使用一个新的对象,复制 str,复制的过程对其判断,是空格则替换,否则直接复制,类似于数组复制
    public static String replaceSpace(StringBuffer str) {
            if (str == null) {
                return null;
            }
            //选用 StringBuilder 单线程使用,比较快,选不选都行
            StringBuilder sb = new StringBuilder();
            //使用 sb 逐个复制 str ,碰到空格则替换,否则直接复制
            for (int i = 0; i < str.length(); i++) {
            //str.charAt(i) 为 char 类型,为了比较需要将其转为和 " " 相同的字符串类型
                if (" ".equals(String.valueOf(str.charAt(i)))){
                    sb.append("%20");
                } else {
                    sb.append(str.charAt(i));
                }
            }
            return sb.toString();
        }

    String,StringBuffer与StringBuilder的区别: https://blog.csdn.net/u011702479/article/details/82262823

    一、Java String 类——String字符串常量
    字符串广泛应用 在Java 编程中,在 Java 中字符串属于对象,Java 提供了 String 类来创建和操作字符串。
    需要注意的是,String的值是不可变的,这就导致每次对String的操作都会生成新的String对象,这样不仅效率低下,而且大量浪费有限的内存空间。我们来看一下这张对String操作时内存变化的图:

    我们可以看到,初始String值为“hello”,然后在这个字符串后面加上新的字符串“world”,这个过程是需要重新在栈堆内存中开辟内存空间的,最终得到了“hello world”字符串也相应的需要开辟内存空间,这样短短的两个字符串,却需要开辟三次内存空间,不得不说这是对内存空间的极大浪费。为了应对经常性的字符串相关的操作,谷歌引入了两个新的类——StringBuffer类和StringBuild类来对此种变化字符串进行处理。

    二、Java StringBuffer 和 StringBuilder 类——StringBuffer字符串变量、StringBuilder字符串变量

    当对字符串进行修改的时候,需要使用 StringBuffer 和 StringBuilder 类。
    和 String 类不同的是,StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象。
    StringBuilder 类在 Java 5 中被提出,它和 StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的(不能同步访问)。
    由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。然而在应用程序要求线程安全的情况下,则必须使用 StringBuffer 类。

      三者的继承结构

    三者的区别:

    (1)字符修改上的区别(主要,见上面分析)

    (2)初始化上的区别,String可以空赋值,后者不行,报错

    ①String

    String s = null;   

    String s = “abc”;   

    ②StringBuffer

    StringBuffer s = null; //结果警告:Null pointer access: The variable result can only be null at this location

    StringBuffer s = new StringBuffer();//StringBuffer对象是一个空的对象

    StringBuffer s = new StringBuffer(“abc”);//创建带有内容的StringBuffer对象,对象的内容就是字符串”

    小结:(1)如果要操作少量的数据用 String;

    (2)多线程操作字符串缓冲区下操作大量数据 StringBuffer;

    (3)单线程操作字符串缓冲区下操作大量数据 StringBuilder。

  • 相关阅读:
    linux安装jenkins
    linux安装python3.8
    python类继承多态
    python字典排序
    第一篇
    第十一周编程总结
    2019春第十周作业
    2019年寒假作业1
    2019年寒假作业3
    学期总结
  • 原文地址:https://www.cnblogs.com/wltree/p/15368146.html
Copyright © 2020-2023  润新知