ошибка: Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 7
При одних значениях s1 и s2 код работает, а при других нет.
import java.util.Arrays;
public class LeetCode {
// метод для удаления символа из строки
static String remove(String str, int a){
String s = "";
for (int i = 0; i < str.length(); i++){
if (i != a){
s = s + str.charAt(i);
}
}
return s;
}
public static void main(String[] args) {
String s1 = "aretheyhere";
String s2 = "yestheyarehere";
String s = s1 + s2;
char[] chars = s.toCharArray();
Arrays.sort(chars);
String sorted = new String(chars);
// удаление символа, если такой уже есть
for (int i = 0; i < sorted.length(); i++){
for (int j = i + 1; j < sorted.length(); j++){
while (sorted.charAt(i) == sorted.charAt(j)){
sorted = remove(sorted, j);
}
}
}
System.out.println(sorted);
}
}
Ответы (1 шт):
Данное исключение указывает на выход за пределы строки при вызове метода String::charAt, который происходит при проверке условия в цикле while, так как внутри этого цикла строка "уменьшается" из-за вызова метода remove, а индексы i, j не меняются.
То есть, в случае продублированного символа в конце строки sorted код попытается найти символ за пределами этой строки.
Для исправления конкретно данной ошибки достаточно добавить проверку j < sorted.length():
while (j < sorted.length() && sorted.charAt(i) == sorted.charAt(j)) {
sorted = remove(sorted, j);
}
Но в целом данное решение для задачи удаления дублированных символов из строки при помощи вспомогательного метода remove (с конкатенацией в цикле), который ещё и вызывается во вложенном цикле for, слишком медленное, так как имеет кубическую сложность O(N3), нивелируя быструю сортировку Arrays.sort.
Можно просто пропускать символы-дубликаты в массиве chars, и использовать StringBuilder для более эффективного получения строки-результата, содержащей только уникальные символы, отсортированные по алфавиту.
// ...
char[] chars = s.toCharArray();
Arrays.sort(chars);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < chars.length; i++) {
sb.append(chars[i]);
while (i < chars.length - 1 && chars[i] == chars[i + 1]) {
i++;
}
}
String sorted = sb.toString();
Ещё более краткое решение с использованием Stream API может выглядеть так:
String streamlined = s.chars() // IntStream кодовых точек
.sorted() // сортируем символы (кодовые точки) из исходной строки
.distinct() // фильтруем: убираем дубликаты
// создаём экземпляр StringBuilder и добавляем отфильтрованные уникальные символы
.collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
.toString(); // конвертируем `StringBuilder` в строку `String`
System.out.println(streamlined);