我正在尝试删除字符串中的重复项,但是我不确定为什么我的算法错误。它给我的输出为baa
,而不是bans
,这是正确的输出。
在尝试调试期间,我尝试在i
内部将j
切换为sb.deleteCharAt();
,但这给了我一个Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 5
错误。
我在做什么错,我该如何解决?
这是我的代码:
public static void removeDuplicate(String s) {
StringBuilder sb = new StringBuilder(s);
for(int i = 0; i < s.length(); i++) {
for(int j = i + 1; j < s.length(); j++) {
if(s.charAt(i) == s.charAt(j)) {
sb.deleteCharAt(i);
}
}
}
System.out.print("Duplicates have been, the resulting string is => " + sb);
}
public static void main(String[] args) {
String s = "bananas";
removeDuplicate(s);
}
答案 0 :(得分:1)
有些错误的地方。您应该在循环中与字符串生成器进行比较,而不是与字符串本身进行比较,因为它会发生变化。其次,您在删除中使用了错误的索引。这是正确的程序:
public static void removeDuplicate(String s) {
StringBuilder sb = new StringBuilder(s);
for(int i = 0; i < sb.length(); i++) {
for(int j = i + 1; j < sb.length(); j++) {
if(sb.charAt(i) == sb.charAt(j)) {
sb.deleteCharAt(j);
}
}
}
System.out.print("Duplicates have been, the resulting string is => " + sb);
}
public static void main(String[] args) {
String s = "bananas";
removeDuplicate(s);
}
输出为:
已重复,结果字符串为=>禁止
答案 1 :(得分:1)
您可以使用distinct():
StringBuilder sb = new StringBuilder();
yourstr.chars().distinct().forEach(c -> sb.append((char) c));
最佳
答案 2 :(得分:0)
基本上,当您删除StringBuilder
中的字符时,可以有效地更改所有其他字符的索引。
在您的示例bananas
中,如果删除第二个a(自我们从0开始,则为pos 3),则得到字符串bannas
。然后,当您想删除bananas
的第3个a时,在位置5,最终删除了s。
答案 3 :(得分:0)
嗯,在循环中删除集合中的元素是一个坏主意,因为它可能基于索引更改导致错误的逻辑。 只需添加诸如“ baaana”之类的特殊情况,您的解决方案就很容易失败,因为当您尝试在索引2处找到“ a”时,您将其删除并跳过与“实际”索引3的比较,因为删除后其索引会减少为2 。 还有另一件事你应该知道。在Java中,String是不可变的,这意味着当您更改字符串时,实际上是为变量分配了新变量。因此,这些函数应该返回一个新的String而不是修改输入。
对于这种类型的问题,我建议您使用哈希数据类型来存储不同的元素,这样您就可以以O(n)的时间复杂度来解决此问题。
public static String removeDuplicate(String s) {
StringBuilder sb = new StringBuilder();
Set<Character> metChars = new HashSet<>();
for(int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if(!metChars.contains(c)) {
sb.append(c);
metChars.add(c);
}
}
return sb.toString();
}