04. 替换空格---《剑指Offer》(Java版)

 《剑指Offer》(Java语言版答案)github链接:

点这

请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。

 对Java语言不太熟悉的同学可能会使用String,但是因为String是不可变的,每次对其进行+-操作,都将新生成一个String,会造成空间和时间的双重浪费。Java在这种情况下建议使用 StringBuilder类不断的进行append()操作.

public String replaceSpace(StringBuffer str) {
        if(str == null){
            return null;
        }
        // 转成char[],虽然多用了些空间,但是[] 比charAt快得多的多
        char[] s = str.toString().toCharArray();
        StringBuffer res = new StringBuffer();
        // 不可以使用forEach,因为foreach不关心顺序,但顺序对本题来说还是十分有用的。
        for (int i = 0; i < s.length; i++) {
            if(s[i] == ' '){
                res.append("%20");
            }else {
                res.append(s[i]);
            }
        }
        return res.toString();
    }

对于C/C++,要考虑的东西比较多,但是Java直接使用造好的轮子StringBuilder即可.

不过作者原意是char数组,那么我也用一下char数组把

public String replaceSpaceByCharArr(String str) {
        if (str == null) {
            return null;
        }
        char[] s = str.toCharArray();
        // 申请一个适当长度的数组,在原来的数组长度上+count(' ')*2即可
        int countSpace = count(s, ' ');
        // 新数组
        char[] resArr = new char[s.length + 2 * countSpace];
        for (int i = 0, j = 0; i < s.length; i++, j++) {
            if (s[i] == ' ') {
                resArr[j++] = '%';
                resArr[j++] = '2';
                resArr[j] = '0';
            } else {
                resArr[j] = s[i];
            }
        }
        // 将Char数组转为String
        return new String(resArr);
    }

    /**
     * 计算在char数组中,target出现的次数
     */
    private int count(char[] s, char target) {
        int res = 0;
        for (char c : s) {
            if (target == c) {
                res++;
            }
        }
        return res;
    }

所有代码如下:

/**
 * 请实现一个函数:
 * 将一个字符串中的每个空格替换成“%20”。
 * 例如
 * <p>
 * 当字符串为We Are Happy.
 * 则经过替换之后的字符串为We%20Are%20Happy。
 */
public class _004_replaceSpace {
    /**
     * 这道题没什么难度,但是有很多初学者喜欢使用String,这是一个大坑的。
     * String 是一个不可变的常量,"+"操作看似改变了String的值,但是原有的值依然存在。
     * 比如:"Login" + "Username" --->这将在内存中出现3个String,一个"Login","Username","LoginUsername"
     * 导致了内存和时间的双重浪费.
     * <p>
     * 对于我们希望能经常改变的字符串,
     * 不考虑线程安全的话:StringBuilder;
     * 考虑线程安全的话:StringBuffer
     */
    public String replaceSpaceByStringBuilder(String str) {
        if (str == null) {
            return null;
        }
        // 转成char[],char[]数组遍历起来会更快,即使转成char[]花费了内存和一定时间,
        // 但对于时间敏感的情况下还是可以考虑的
        char[] s = str.toCharArray();
        StringBuffer res = new StringBuffer();
        // foreach在这种情况下也是顺序的。
        for (char c : s) {
            // 遇到空格,则在res后面家伙是那个"%20",与String的 str+="%20" 操作结果一样。
            if (c == ' ') {
                res.append("%20");
            } else {
                // 非空格,直接添加至末尾即可
                res.append(c);
            }
        }
        // 将StringBuilder转为String,返回即可
        return res.toString();
    }

    /**
     * 剑指Offer中使用的是char[],这里也实现原地和原地。
     * <p>
     * 如果内存足够并且的话,使用双数组呗.
     */
    public String replaceSpaceByCharArr(String str) {
        if (str == null) {
            return null;
        }
        char[] s = str.toCharArray();
        // 申请一个适当长度的数组,在原来的数组长度上+count(' ')*2即可
        int countSpace = count(s, ' ');
        // 新数组
        char[] resArr = new char[s.length + 2 * countSpace];
        for (int i = 0, j = 0; i < s.length; i++, j++) {
            if (s[i] == ' ') {
                resArr[j++] = '%';
                resArr[j++] = '2';
                resArr[j] = '0';
            } else {
                resArr[j] = s[i];
            }
        }
        // 将Char数组转为String
        return new String(resArr);
    }

    /**
     * 计算在char数组中,target出现的次数
     */
    private int count(char[] s, char target) {
        int res = 0;
        for (char c : s) {
            if (target == c) {
                res++;
            }
        }
        return res;
    }


}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值