用%20替换空格时的长度值

时间:2015-09-16 19:59:12

标签: 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); } } } 替换空格来破解编码专访第5版的问题:

  

编写一个方法,用'%20'替换字符串中的所有空格。您可以假设字符串在字符串末尾有足够的空间来容纳其他字符,并且您将获得" true"字符串的长度。 (注意:如果在Java中实现,请使用字符数组,以便您可以就地执行此操作)

我的算法是:

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

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

17

我有两个问题:

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

  2. 目的是什么:{{1}}

4 个答案:

答案 0 :(得分:1)

我们并非都有这本书,但是从待处理的编辑中,我看到确切的问题是:

  

编写一个方法,用'%20'替换字符串中的所有空格。您可以假设字符串在字符串末尾有足够的空间来容纳附加字符,并且您将获得字符串的“true”长度。 (注意:如果在Java中实现,请使用字符数组,以便您可以就地执行此操作

从破解编码面试第5版

因此,它表示您的input参数应为char[]

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

问题1:

  

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

你自己回答了。如果长度为17,则索引为0到16.如果数组长度仅为17,则使用IndexOutOfBoundsException访问索引17。

问题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;
}

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

答案 1 :(得分:1)

下面发布的代码效果很好。干杯。 Sample Output

test = 'pam' -> map
test = 'enni' -> nine
test = 'yfunn' -> funny

答案 2 :(得分:0)

我相信您的直接问题已在评论中得到解答,因此我将重点关注所写方法的问题。

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

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

因此,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();
}

在开头将整个String转换为char[]可能更为理想,并迭代数组而不是使用String.charAt(i)。我们可以根据预期的空间数将现有字符串的长度乘以某个常量,为StringBuilder选择更合适的填充。对于非常大的字符串,在声明我们的数组之前首先计算空格的数量甚至是有意义的,但这些优化留给了读者。

答案 3 :(得分: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();
  }