剑指Offer:替换空格

请实现一个函数,把字符数组中的每个空格替换为”%20”。例如输入”we are happy.”则输出”we%20are%20happy.”
原来的一个空格被替换为‘%’‘2’‘0’我们不能想当然的直接赋值字符,而必须将空格后面的所有字符都后移两个位置否则会覆盖原来的字符。

时间复杂度为O(n^2)的解法,不足以拿到Offer

在我们平常看到数组这玩意儿时我们总是从前往后遍历,同样在解答这题时也会从前往后一个个遍历,如果遇到空格就将空格后面的字符都后移2位,直至遇到结尾。拿题目中的例子来说由于遇到两个空格”happy.”这一部分被反复的向后移动了两次,这太多余了。
以下是这种解法的流程:
这里写图片描述
这种解法的代码我就不贴出来害人了,提及只是提醒大家!!!

时间复杂度为O(n)的解法,搞定Offer

从前往后遍历会导致部分字符重复的移动,那么如果我们从后向前遍历呢?
以下是从后向前的解法流程:
这里写图片描述
从后向前遍历中没有出现重复移动两次的现象,并且happy.在第一次移动中就移到了最终位置,这是因为字符数组中有两个空格,那么这个字符数组长度会增加4,我们能知道最终的结尾部分在哪里。从而直接将happy.移动到最终目的位置。

以下贴出这种解法的代码:

//从后往前扫描
public class ReplaceSpace {
    public static void main(String[] args) {
        String str = "we are happy.";
        char[] chs = new char[20];
        for(int i=0;i<str.length();i++){
            chs[i] = str.charAt(i);
        }
        printf(replace(chs));
    }

    public static int strlen(char[] chs){
        if(chs==null){
            return -1;
        }
        int i=0,count=0;
        while(chs[i]!='\0'){
            i++;
            count++;
        }
        return count;
    }
    public static void printf(char[] chs){
        if(chs==null){
            return;
        }
        int i=0;
        while(chs[i]!='\0'){
            System.out.print(chs[i]);
            i++;
        }
    }
    public static char[] replace(char[] chs){
        if(chs==null){
            return null;
        }
        char ch;
        int i=0;
        int j=i;
        int count=0;//记录空格数
        //首先遍历一遍记录下空格数目
        while(chs[i]!='\0'){
            if(chs[i]==' '){
                count++;
            }
            i++;
        }
        i--;
        //一个空格要后移2位,count个空格要后移2*count位
        j = i + 2*count; 
        while(i>=0){
            chs[j] = chs[i];
            if(chs[i]==' '){
                chs[j]='0';
                chs[--j]='2';
                chs[--j]='%';
            }
            i--;
            j--;
        }
        return chs;
    }

    //使用char[]更麻烦一点,为了让C语言的看官看懂,使用StringBuffer更简短
    public static String replaceSpace(StringBuffer str) {
        int countSpace = 0;//countSpace为计算空格数
        for(int i=0;i<str.length();i++){
            if(str.charAt(i)==' ')
                countSpace++;
        }
        int indexold = str.length()-1; //indexold为为替换前的str下标
        int newlength = str.length() + countSpace*2;//计算空格转换成%20之后的str长度
        int indexnew = newlength-1;//indexold为为把空格替换为%20后的str下标
        str.setLength(newlength);//使str的长度扩大到转换成%20之后的长度,防止下标越界
        for(;indexold>=0 && indexold<newlength;--indexold){ 
                if(str.charAt(indexold) == ' '){  
                    str.setCharAt(indexnew--, '0');
                    str.setCharAt(indexnew--, '2');
                    str.setCharAt(indexnew--, '%');
                }else{
                    str.setCharAt(indexnew--, str.charAt(indexold));
                }
        }
        return str.toString();
    }

}

测试结果:
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值