2015-09-16 75 views
4

我从破解编码采访第五版关于更换空间的问题正在与%20用%替换空间时,长度值20

写一个方法,以取代所有空格用“字符串%20' 。您可能会认为字符串在字符串的末尾有足够的空间来容纳额外的字符,并且您将得到字符串的“真实”长度。 (注:如果用Java实现,请使用字符数组,这样就可以在地方执行此操作)

算法我是:

public static void replaceSpaces(String input, int length) { 

    char[] str = input.toCharArray(); 

    int spaceCount = 0; 
    for(int i = length - 1; i >= 0; i--){ 
     if(str[i] == ' ') { 
      spaceCount++; 
     } 
    } 

    int newLength = length + spaceCount * 2; 

    str[newLength] = '\0'; 

    for(int i = length - 1; i >= 0; i--) { 
     if(str[i] == ' ') { 
      str[newLength - 1] = '0'; 
      str[newLength - 2] = '2'; 
      str[newLength - 3] = '%'; 
      newLength = newLength - 3; 
      System.out.println(str); 
     } else { 
      str[newLength - 1] = str[i]; 
      newLength = newLength - 1; 
      System.out.println(str); 
     } 
    } 
} 

打印输出功能的每一步,这里是我的输出:

Mr John Smith h 
Mr John Smith th 
Mr John Smith ith 
Mr John Smithmith 
Mr John SmitSmith 
Mr John S%20Smith 
Mr John n%20Smith 
Mr Johnhn%20Smith 
Mr Johohn%20Smith 
Mr JoJohn%20Smith 
Mr%20John%20Smith 
Mr%20John%20Smith 
Mr%20John%20Smith 

我有两个问题:

  1. 我们知道字符串的新长度是17。我不明白的是,为什么我们需要有[newLength - 1]而不是[newLength]。我们有兴趣替换当前的指数,不是吗?或者是因为新的长度是17,但是当转换为索引时,它实际上是16(第0个索引)。

  2. 是什么目的:str[newLength] = '\0';

+4

在C中, “字符串” 是空终止。也许这个代码是一个过度直接的端口? – azurefrog

+4

可以肯定的是:你知道你可以使用'String.replace(“”,“%20”);'相反,对吗? – Tom

+0

@Tom这是一个面试问题 - 我希望我能在面试时这样做。 – theGreenCabbage

回答

1

我们不都有这本书,但是从挂起的编辑,我看到确切的问题是:

写法“%20”替换字符串中的所有空间。您可能会认为字符串在字符串的末尾有足够的空间来容纳额外的字符,并且您将得到字符串的“真实”长度。 (注:如果用Java实现,请使用字符数组,这样就可以在地方执行此操作)

开裂的编码采访第五版


所以,说你的input参数应该是char[]

由于您正在更改文本的长度,因此您的方法需要返回新的长度。


问题1:

我们知道该字符串的新长度是17。我不明白的是,为什么我们需要有[newLength - 1]而不是[newLength ]。我们有兴趣替换当前的指数,不是吗?或者是因为新的长度是17,但是当转换为索引时,它实际上是16(第0个索引)。

你自己回答。长度为17时,索引值为0到16.如果阵列只有17个长度,则访问索引17并抛出IndexOutOfBoundsException


问题2:

是什么的目的:STR [newLength] = '\ 0';

没有任何。这是无效的,在Java中没有用处。去掉它。

Java字符串有length()。在C中,字符串是零终止的,但不是Java。


测试代码,试图用这种运行它:

char[] buffer = { 'M','r',' ','J','o','h','n',' ','S','m','i','t','h','*','*','*','*' }; 
int inLen = 13; 
System.out.println("buffer: '" + new String(buffer) + "'"); 
System.out.println("inLen : " + inLen); 
System.out.println("input : '" + new String(buffer, 0, inLen) + "'"); 
int outLen = replaceSpaces(buffer, inLen); 
System.out.println("outLen: " + outLen); 
System.out.println("result: '" + new String(buffer, 0, outLen) + "'"); 

输出应该是:

buffer: 'Mr John Smith****' 
inLen : 13 
input : 'Mr John Smith' 
outLen: 17 
result: 'Mr%20John%20Smith' 

的方法访问input[17]将抛出IndexOutOfBoundsException


这是基于所示的代码,以下引用的文字一个可能的实现,并停止处理一旦所有空格代替。

public static int replaceSpaces(char[] str, int length) { 
    int spaceCount = 0; 
    for (int i = length - 1; i >= 0; i--) 
     if (str[i] == ' ') 
      spaceCount++; 
    int shift = spaceCount * 2; 
    int newLength = length + shift; 
    for (int i = newLength - 1; shift > 0; i--) { 
     char c = str[i - shift]; 
     if (c != ' ') { 
      str[i] = c; 
     } else { 
      str[i] = '0'; 
      str[--i] = '2'; 
      str[--i] = '%'; 
      shift -= 2; 
     } 
    } 
    return newLength; 
} 

这产生了上述测试代码的预期输出。

+0

但是'str [newLength] ='\ 0''正在访问该索引,所以它不是越界。这个解决方案实际上来自这本书:https://github.com/gaylemcd/ctci/blob/master/java/Chapter%201/Question1_4/Question.java – Zarwan

+1

@Zar我不知道那些引用代码是什么,但它*不是*对Java *中的问题*的正确答案。 Java不会用'\ 0'来终止文本,并且这个问题并没有提到任何关于它的必要,所以对于Java *来说,代码是错误的。 – Andreas

+0

如果你看看做回购的账户,它是这本书的作者。我同意它没有这条线,我的个人解决方案不使用它。但它仍然是一个有效的事情,如果你在代码库中运行代码,它就可以工作。我只是想知道她为什么选择这样做。 – Zarwan

0

我相信,你的直接问题都在评论中已经回答了,所以在这里,而不是我将重点放在与方法问题的书面。

忽略在基类String类(以及许多其他第三方字符串实用程序类)中已存在此功能的事实,我们仍然可以编写基本的字符串替换函数。写在问题中的函数似乎不是为Java编写的,并且不返回任何值,因为字符串是不可变的,这意味着函数不可能实现其名称。

相反,我们需要创建一个新的数组,我们将现有字符复制到一个新数组中,同时替换我们遇到的任何空格%20。然后我们将这个数组作为新的String返回。方便的是,Java有一个类封装了一个可变大小的字符数组,我们可以使用它来组装我们的新字符串StringBuilder

所以在Java中的简单和工作(而不是优化)替换功能可能看起来像:

public static String replaceSpaces(String input) 
{ 
    if (input == null) return null; 

    // New string builder with some padding to account for replacements... 
    // Padding was chosen pretty arbitrarily, there are certainly better values. 
    StringBuilder builder = new StringBuilder(input.length() + 128); 

    for (int i = 0; i < input.length(); i++) 
    { 
     char c = input.chatAt(i); 
     if (c == ' ') { 
      builder.append("%20"); 
     } else { 
      builder.append(c); 
     } 
    } 

    return builder.toString(); 
} 

这可能是更优的整个字符串到char[]转换的开始,遍历数组而不是使用String.charAt(i)。我们可以为StringBuilder选择一个更合适的填充,方法是根据预期的空间数量,将现有字符串的长度乘以某个常数。对于非常大的字符串,甚至可以在声明数组之前先计算空格的数量,但这些优化仍然是读者的练习。

+1

不应该在else语句中添加'c'而不是空格吗?你的解决方案实际上要干净得多,我不相信我没有想到它。也就是说,如果他们不允许使用除基本数据结构之外的任何内容,我将无法使用它。 – theGreenCabbage

+1

@ theGreenCabbage是的,你是对的!我的不好,我从来没有测试过,只是在文本区域写下来。好的解决方案已被编辑。 –

+0

由此判断..您的解决方案应该是'O(n)',因为您只需对数组进行全面传递并根据需要添加元素? – theGreenCabbage

1

下面的代码很好用。干杯。 Sample Output

package StringAndArray; 


public class Question_Four_Replace_Spaces { 

public static void main(String[] args) { 
    String string = "Mr Shubham Dilip Yeole"; 
    char[] array = string.toCharArray(); 
    System.out.println("\n\nInput : " +string); 
    System.out.println("\n\nResult: "+method_1(array,string.length())); 
    method_1(array,string.length()); 
} 


private static String method_1(char[] array, int length) { 
    int spaceCount = 0; 
    for(int i=0; i<array.length; i++){ 
     if(array[i]==' ') spaceCount++; 
    } 
    int count = 0; 
    int newLength = length + spaceCount*2; 
    char[] newArray = new char[newLength]; 

    for(int i= 0; i<array.length; i++){ 
     if(array[i]==' '){ 
      newArray[count++] = '%'; 
      newArray[count++] = '2'; 
      newArray[count++] = '0'; 
     }else{ 
      newArray[count] = array[i]; 
      count++; 
     } 
    } 
    String newString1 = new String(newArray); 

    return newString1; 
} 
} 
0
@Test public void replaceTest() { 
    String s = "Mr John Smith  "; 
    char[] chars = s.toCharArray(); 
    int length = 13; 
    char[] chars1 = subString(chars, length); 
    //actualString = actualString.replace(" ", "%20"); 
    Assert.assertEquals(replace(chars1, "%20"), "Mr%20John%20Smith"); 
    } 

    private char[] subString(char[] chars, int length) { 
    char[] newChar = new char[length]; 
    for (int i = 0; i < length; i++) { 
     newChar[i] = chars[i]; 
    } 

    return newChar; 
    } 

    private String replace(char[] chars, String s) { 
    StringBuilder builder = new StringBuilder(); 
    for (int i = 0; i < chars.length; i++) { 
     if (chars[i] == ' ') { 
     builder.append(s); 
     } else { 
     builder.append(chars[i]); 
     } 
    } 
    return builder.toString(); 
    } 
+0

谢谢,但这个问题已经得到解答 – theGreenCabbage