Когда вы вычисляете анаграммы, вы можете воспользоваться свойством операции XOR , которая гласит, что если вы xor двух одинаковых чисел, вы получите 0.
Поскольку символы в строках по существу, просто числа, вы можете запустить xor для всех символов обеих строк, и если результат равен 0, то эти строки являются анаграммами.
Вы можете перебрать обе строки, используя l oop, но если вы хотите использовать Рекурсия, я бы посоветовал вам преобразовать вашу строку в списки символов.
Списки позволяют эффективно разделять первый элемент (заголовок списка) и остальные (хвост списка). Таким образом, решение будет go следующим образом:
- Разбить список по заголовкам и хвостам для обоих списков символов.
- Выполнить xor над символами, извлеченными из заголовков списков и предыдущего результата.
- Передача хвостов списка и результата хоринга следующему рекурсивному вызову.
Когда мы добираемся до конца списков, мы просто возвращаем true - это регистр xoring равен 0 .
Последняя оптимизация, которую мы можем сделать - это короткое замыкание с false всякий раз, когда передаются строки различной длины (так как они никогда не могут быть анаграммами в любом случае) .
Окончательное решение:
def anagram(a: String, b: String): Boolean = {
//inner function doing recursion, annotation @tailrec makes sure function is tail-recursive
@tailrec
def go(a: List[Char], b: List[Char], acc: Int): Boolean = { //using additional parameter acc, allows us to use tail-recursion, which is safe for stack
(a, b) match {
case (x :: xs, y :: ys) => //operator :: splits list to head and tail
go(xs, ys, acc ^ x ^ y) //because we changed string to lists of chars, we can now efficiently access heads (first elements) of lists
//we get first characters of both lists, then call recursively go passing tails of lists and result of xoring accumulator with both characters
case _ => acc == 0 //if result of xoring whole strings is 0, then both strings are anagrams
}
}
if (a.length != b.length) { //we already know strings can't be anagrams, because they've got different size
false
} else {
go(a.toList, b.toList, 0)
}
}
anagram("twelveplusone", "elevenplustwo") //true
anagram("amina", "minia") //false