用于删除字符串中重复字符的函数

2022-09-01 09:13:05

下面的代码正在尝试删除字符串中的任何重复字符。我不确定代码是否正确。任何人都可以帮助我处理代码(即当字符匹配时实际发生了什么)?

public static void removeDuplicates(char[] str) {
  if (str == null) return;
  int len = str.length;
  if (len < 2) return;
  int tail = 1;
  for (int i = 1; i < len; ++i) {
    int j;
    for (j = 0; j < tail; ++j) {
      if (str[i] == str[j]) break;
    }
    if (j == tail) {
      str[tail] = str[i];
      ++tail;
    }
  }
  str[tail] = 0;
}

答案 1

该功能对我来说看起来很好。我写了内联评论。希望它有帮助:

// function takes a char array as input.
// modifies it to remove duplicates and adds a 0 to mark the end
// of the unique chars in the array.
public static void removeDuplicates(char[] str) {
  if (str == null) return; // if the array does not exist..nothing to do return.
  int len = str.length; // get the array length.
  if (len < 2) return; // if its less than 2..can't have duplicates..return.
  int tail = 1; // number of unique char in the array.
  // start at 2nd char and go till the end of the array.
  for (int i = 1; i < len; ++i) { 
    int j;
    // for every char in outer loop check if that char is already seen.
    // char in [0,tail) are all unique.
    for (j = 0; j < tail; ++j) {
      if (str[i] == str[j]) break; // break if we find duplicate.
    }
    // if j reachs tail..we did not break, which implies this char at pos i
    // is not a duplicate. So we need to add it our "unique char list"
    // we add it to the end, that is at pos tail.
    if (j == tail) {
      str[tail] = str[i]; // add
      ++tail; // increment tail...[0,tail) is still "unique char list"
    }
  }
  str[tail] = 0; // add a 0 at the end to mark the end of the unique char.
}

答案 2

很抱歉,你的代码非常像C。

Java 不是 .您说要从 中删除重复项,但您取而代之。Stringchar[]Stringchar[]

这是 -终止吗?看起来不像,因为你取了整个数组。但是,您的算法会尝试终止数组的一部分。如果数组不包含重复项,会发生什么情况?char[]\0.length\0

好吧,在编写时,您的代码实际上在最后一行抛出了一个!没有空间,因为所有的插槽都用完了!ArrayIndexOutOfBoundsException\0

您可以在此特殊情况下添加一个不添加的检查,但是您打算如何使用此代码呢?您是否打算使用类似 -的函数来查找数组中的第一个函数?如果没有,会发生什么?(由于上面所有独特的特殊情况?\0strlen\0

如果原始 / 包含 ?(顺便说一句,这在Java中是完全合法的,请参阅JLS 10.9字符数组不是字符串。Stringchar[]\0)

结果将是一团糟,这一切都是因为你想做所有类似C的事情,并且在没有任何额外缓冲区的情况下就地。您确定真的需要这样做吗?为什么不使用 、 、 、 和 所有更高级别的 API?是可证明它太慢了,还是你只是怀疑它是?StringindexOflastIndexOfreplaceString

“过早优化是一切罪恶的根源”。我很抱歉,但是如果你甚至无法理解原始代码的作用,那么弄清楚它将如何适应更大(更混乱)的系统将是一场噩梦。


我的最小建议是执行以下操作:

  • 使函数接受并返回一个 ,即Stringpublic static String removeDuplicates(String in)
  • 在内部,与char[] str = in.toCharArray();
  • 将最后一行替换为return new String(str, 0, tail);

这确实使用了额外的缓冲区,但至少与系统其余部分的接口要干净得多。


或者,您可以这样使用:StringBuilder

static String removeDuplicates(String s) {
    StringBuilder noDupes = new StringBuilder();
    for (int i = 0; i < s.length(); i++) {
        String si = s.substring(i, i + 1);
        if (noDupes.indexOf(si) == -1) {
            noDupes.append(si);
        }
    }
    return noDupes.toString();
}

请注意,这基本上与您拥有的算法相同,但要干净得多,并且没有那么多的小角落案例等。