剑指offer5-字符串

题目

将一个字符串中的空格替换成 "%20"

思路

 1.首先最容易想到的当然是新建一个字符串,从前往后,如果碰到一个空格,那么就添加在新字符串中添加"%20";如果碰到正常字符,就存入正常字符。(这是如果题目中允许创建新的字符串的情况)

2.(如果不允许新建字符串,而是要求在原来的字符串上进行替换,但是保证输入的字符串后面有足够多的空余内存)那么最简单的方法就是从前往后,碰到空格字符的时候进行替换,由于是把1个字符替换为3个字符串,因此还需要先把后面的字符串往后移两位,再进行插入。但是这样的话,对于每个空格,都会将空格后面的O(n)字符往后移动一次,因此对于含有O(n)个空格字符的字符串,时间复杂度为O(n^2)。

3.这类问题最理想的解答应该是从后往前进行替换。由于遍历一遍字符串,就可以统计出空格的个数,从而得到原字符串再替换后增加的字符数。设置两个指针,分别P1指向原始字符串的末尾,和P2指向替换后字符串的末尾,P1向前移动将字符复制到P2指针的位置,从而P2也向前移动,如果替换到空格,那么就在P2处添加"%20",P2指针同时继续向前移动(注意逆序)

解法

    public static void replaceSpace(StringBuffer str) {
        int P1=str.length()-1;
        for(int i=0; i<=P1;i++) {
            if(str.charAt(i)==' ') {
                str.append("  ");
            }
        }
        int P2=str.length()-1;
        while(P1>=0 && P2>P1) {
            char c=str.charAt(P1--);
            if(c==' ') {
                str.setCharAt(P2--, '0');
                str.setCharAt(P2--, '2');
                str.setCharAt(P2--, '%');
            }
            else {
                str.setCharAt(P2--, c);
            }
        }
        System.out.print(str);
    }

 

 

题目 

有两个排序的数组A1和A2,内存在A1的末尾有足够的空余空间容纳A2。请写一个函数,把A2的所有数字插入A1中,并且所有的数字是排序的。

思路

借鉴上题的思路,本题就应该从后往前,由于是有序排列的数组,那么不断比较数组的最后一位数字,将更大的数字其往数组A1的最后位置(数组A1的长度为num1和num2的长度之和)添加。

需要注意的是,两个数组长度不一致,记得要处理剩余部分。当某一个数组未添加到新序列的部分为0时,说明这个数组已经添加完,那么直接将另一个数组未添加的部分添加即可。

解法

    public static void replaceSpace2(int[] num1, int[] num2, int length1, int length2) {
        //int len1=num1.length-1;
        //int len2=num2.length-1;
        int len1=length1-1;
        int len2=length2-1;
        int mergeLen=length1+length2-1;
        while(len1>=0 && len2>=0) {
            if(num1[len1]>num2[len2]) {
                num1[mergeLen]=num1[len1];
                len1--;
                mergeLen--;
            }
            else if(num1[len1]<num2[len2]) {            
                num1[mergeLen]=num2[len2];
                len2--;
                mergeLen--;
            }
            else {
                num1[mergeLen--]=num1[len1--];
                num1[mergeLen--]=num2[len2--];
            }
        }
        while(len1>=0) {
            num1[mergeLen--]=num1[len1--];
        }
        while(len2>=0) {
            num1[mergeLen--]=num2[len2--];
        }
        System.out.print(num1);
    }

 

扩展--StringBuffer类和StringBuilder类

String类不可修改,一旦创建String对象,其值就无法改变了(最开始赋值时在常量池中开辟的空间的内容不能被修改)。对字符串进行修改时,需要使用StringBuffer类和StringBuilder类,这两种类的对象能够被多次修改,并且不产生新的未使用对象。

StringBuilder和 StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的(不能同步访问)。但是由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。然而在应用程序要求线程安全的情况下,则必须使用 StringBuffer 类

常用方法:

//StringBuffer
public StringBuffer() //无参构造方法
public StringBuffer(int capacity) //指定容量的字符串缓冲区对象
public StringBuffer(String str) //指定字符串内容的字符串缓冲区对象
public insert(int offset, int i) //将 int 参数的字符串表示形式插入此序列中
public delete(int start, int end) //移除此序列的子字符串中的字符
replace(int start, int end, String str) //使用给定 String 中的字符替换此序列的子字符串中的字符

//与String类中类似的方法
public int capacity() //返回当前容量,理论值
public int length() //返回长度(字符数) ,实际值
char charAt(int index) //返回此序列中指定索引处的 char 值
int indexOf(String str) //返回第一次出现的指定子字符串在该字符串中的索引
void setLength(int newLength) //设置字符序列的长度
String substring(int start)返回一个新的 String,它包含此字符序列当前所包含的字符子序列
void setCharAt(int index, char ch) //将给定索引处的字符设置为 ch
String toString() //返回此序列中数据的字符串表示形式

猜你喜欢

转载自www.cnblogs.com/lyeeer/p/12194108.html