劍指Offer面試題4:替換空格 Java實現

題目:請實現一個函數,把字符串中的每個空格替換成“20%”。例如,輸入“we are so happy”則輸出:“we20%are20%so20%happy”。
算法分析:

算法1:時間複雜度爲O(n^2)的解法
現在我們考慮怎麼做替換操作。最直觀的做法是從頭到尾掃描字符串,每一次碰到空格字符的時候做替換。由於是把1個字符替換稱3個字符,我們必須把空格後面的所有的字符都後移兩個字節,否則就有兩個字符被覆蓋了。
舉個例子,我們從頭到尾把“We are happy"中的每一個空格替換成”%20“。爲了形象期間,我們可以用一個表格來表示字符串,表格中的每個格子表示一個字符。如下圖所示:
 
我們替換了第一個空格,這個字符串編程圖b中的內容,表格中灰色背景表示需要移動的字符。接着我們替換第二個空格,替換之後的內容如圖c所示。同時我們注意到用深灰色的北京標註”happy“部分被移動了兩次。
假設字符的長度是n。對每個空格字符,需要移動後面O(n)個字符,因此對含有O(n)個空格字符串而言總的時間效率是O(n2).
當我們把這種思路闡述給面試官後,他不會就此滿意,他將讓我們尋找更快的方法。在前面的分析中,我們發現數組中的很多字符都移動了很多次,能不能減少移動的次數呢?我們換一種思路,把從前向後替換成從後向前替換。

算法2:時間複雜度爲O(n)的解法
我們先遍歷一次字符串,這樣就能夠統計出字符串中空格的綜述,並可以計算出替換之後字符串的總的長度。每替換一個空格,長度增加2,因此替換以後的字符串的長度等於原來的長度加上2乘以空格的數目,我們還是以前面的字符串”We are happy"爲例,“We are happy"這個字符串的長度是14,裏面有兩個空格,因此替換之後的字符串的長度爲18
我們從字符串的後面開始複製和替換。首先準備兩個指針,P1和P2.   P1指向原始字符串的末尾,而P2指向替換之後的字符串的末尾。接下來我們向前移動指針P1,逐個把它指向的字符複製到P2指向的位置,直到碰到第一個空格爲止。此時字符串包含如下圖b所示,灰色陰影的區域是做了字符拷貝的區域。碰到第一個空格之後,把P1向前移動一格,在P2之前插入字符串”%20“,由於”%20“的長度爲3,同時也要把P2向前移動3格如圖所示。
我們接着向前複製,直到碰到第二個空格(d)所示。和上一次一樣,我們再把P1向前移動1格,並把P2向前移動3格插入”%20“(如圖e),此時P1,P2指向同一個位置,表明所有的空格都已經替換完畢。
從上面的分析我們可以看出,所有的字符都只複製一次,因此這個算法的時間效率是O(n),比第一個思路要快。
 

遇到問題及解決方案:
1.Exception in thread main java.lang.ArrayIndexOutOfBoundsException問題
解決方法:提示此錯誤表示字符串數組越界,即超出了字符數組的長度,仔細檢查各個字符數組的長度。
 2.構造函數不能有返回值 
3.對構造函數傳遞參數時可以不生成對象,直接生成匿名對象傳遞參數
 //replaceFun repl = new replaceFun(c);   //在生成對象時傳遞參數  
        new replaceFun(c);            //匿名對象,直接向構造函數中傳遞參數  
算法源程序:
/**************************************************************      
* Copyright (c) 2016, 北京郵電大學          
* All rights reserved.                   
* 版 本 號:v1.0                   
* 題目描述:實現一個函數,把字符串中的每個空格都替換成“20%”.例如:輸入we are so happy ,則輸出: 
*           we20%are20%so20%happy. 
* 輸入描述:請輸入一段字符串: 
*           we are so happy 
* 程序輸出: we20%are20%so20%happy 
* 問題分析:1.Exception in thread main java.lang.ArrayIndexOutOfBoundsException問題 
*       解決方法:提示此錯誤表示字符串數組越界,即超出了字符數組的長度,仔細檢查各個字符數組的長度。 
*       2.構造函數不能有返回值 
* 算法描述:1.先遍歷一遍數組,統計出字符串中的空格個數,並可由此計算出替換後的字符串的長度,每替換一個空格, 
*       字符串的長度都增加2,因此替換後的字符串的長度等於原來的字符串的長度再加上2*空格數目。 
*       2.使用函數System.arraycopy()將原數組s複製一份到數組newArray中,函數原型是:  
*       public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length) 
*       src:源數組; srcPos:源數組要複製的起始位置; dest:目的數組; 
*       destPos:目的數組放置的起始位置; length:複製的長度。 
*       這樣做的原因:新生成的數組的第一個空格前的字符爲空,無法顯示,當複製一次原數組後, 
*       新數組的第一個空格前即不爲空。 
*       3.字符串數組中存放的是字符串,而字符數組中存放的是每一個字符。 
* 完成時間:2016-03-04
***************************************************************/  
 
package org.marsguo.offerproject;

import java.util.Scanner;  
class replaceFun{  
    private static int count = 0;  
    public  replaceFun(char[] s){                   //構造函數  
        for(int i = 0;i < s.length; i++){            //判斷空格的個數  
            if(s[i] == ' '){  
                count++;                            //遇到空格則count+1  
            }  
        }  
        System.out.println("count的值爲:" + count);  
          
         int originalLenght = s.length-1;               //初始長度爲s長度減1  
         int newLength = s.length+count*2;              //新生成的數組長度   
         System.out.println("newLength長度爲:" + newLength);  
         System.out.println("originalLength長度是:"+ originalLenght);  
         char[] newArray = new char[newLength];         //新聲明一個數組newArray  
         /*使用函數System.arraycopy()將原數組s複製一份到數組newArray中, 
		這樣做的原因:新生成的數組的第一個空格前的字符爲空,無法顯示,當複製一次原數組後, 
		新數組的第一個空格前即不爲空,*/  
         System.arraycopy(s,0,newArray,0,s.length);    
           
         while(originalLenght >= 0&&newLength > originalLenght){      //  
            if(s[originalLenght] == ' '){           //判斷是否遇到空格  
                newArray[--newLength] = '%';        //newLength先自減1 ,後在放入newArray數組中  
                newArray[--newLength] = '0';  
                newArray[--newLength] = '2';  
            }else{                              //如果沒有遇到空格,則將原數組的字符從後向前放入新數組的從後向前中  
                newArray[--newLength] = s[originalLenght];  
            }  
            originalLenght--;  
         }  
        //return newArray;    構造函數不能有返回值,不能有函數類型!!!  
        System.out.println("替換後的字符串爲:");  
        for(int i = 0 ; i<newArray.length; i ++){  
            System.out.print(newArray[i]);  
        }  
    }  
    public static void print(char[] newArray){  
//      System.out.println("替換後的字符串爲:");  
//      for(int i = 0 ; i<newArray.length; i ++){  
//          System.out.print(newArray[i]);  
//      }  
    }  
}  
  
/*第二種算法: 
*使用java自帶的replace()函數,將一個輸入的字符串中的所有空格都直接替換爲20%; 
*/
class SolutionMethod2{
	 public String replaceString(final String inputString) { 
	        return inputString.replace(" ", "%20"); 
	 }
}

public class ReplaceBlank{  
    public static void main(String args[]){  
          
        Scanner sc = new Scanner(System.in);  
        System.out.println("請輸入一串包含空格的英文字符串:");  
        String str = sc.nextLine();//這裏出現問題!!!!輸入帶空格的字符串時,需要用.nextLine();而不是.next();  
        System.out.println("str是:"+ str);  
        
        sc.close();
        //String s[] = new String[str.length()];  //此處生成新的字符串數組時,判斷字符串長度用str.length()而不是str.length  
        char[] c = str.toCharArray();               //將字符串轉化爲字符型數組中  
        //replaceFun repl = new replaceFun(c);   //在生成對象時傳遞參數  
        new replaceFun(c);			//匿名對象,直接向構造函數中傳遞參數
        //replaceFun(c);     
        //repl.print();   //調用類中的方法不能用repl.print(replaceFun(s)),而是直接使用對象名.方法(參數)  
        
        System.out.println();
        SolutionMethod2 solution2 = new SolutionMethod2();
        System.out.println("算法2輸出:" + solution2.replaceString(str));
    }  
}  
  
  
/*第二種算法: 
*使用java自帶的replace()函數,將一個輸入的字符串中的所有空格都直接替換爲20%; 
public static void main(final String[] args) { 
        String string = "We Are Happy"; 
        System.out.println(replaceString(string)); 
    } 
  
    public static String replaceString(final String inputString) { 
        return inputString.replace(" ", "%20"); 
    } 
*/  

程序運行結果:



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章