177 lines
12 KiB
Markdown
177 lines
12 KiB
Markdown
![]() |
---
|
|||
|
title: No Repeats Please
|
|||
|
localeTitle: Нет повторений Пожалуйста
|
|||
|
---
|
|||
|
 Не забудьте использовать **`Read-Search-Ask`** если вы застряли. Попробуйте подключить программу  и напишите свой собственный код 
|
|||
|
|
|||
|
###  Проблема Объяснение:
|
|||
|
|
|||
|
Эта задача требует от нас вернуть количество полных перестановок предоставленной строки, которые не имеют повторяющихся последовательных букв. Предполагается, что все символы в предоставленной строке уникальны. Например, `aab` должен возвращать 2, поскольку имеет 6 полных перестановок ( `aab` , `aab` , `aba` , `aba` , `baa` , `baa` ), но только 2 из них ( `aba` и `aba` ) не имеют одинаковой буквы (в данном случае `a` ) повторяющееся.
|
|||
|
|
|||
|
Для этого нам нужно будет посмотреть каждую возможную перестановку строки. Существует несколько способов сделать это. Общим вопросом интервью является построение функции, которая собирает все перестановки строки. В Интернете есть несколько учебных пособий о том, как это сделать.
|
|||
|
|
|||
|
#### Потенциальные методы, используемые в качестве решения
|
|||
|
|
|||
|
##### Рекурсивный метод
|
|||
|
|
|||
|
Эта задача может быть сложной даже после просмотра учебника. Чтобы написать рекурсивное решение, вы хотите отправить каждое новое использование функции три входа:
|
|||
|
|
|||
|
1. Создается новая строка (или массив символов).
|
|||
|
2. Позиция в новой строке, которая будет заполнена дальше.
|
|||
|
3. Идея о том, какие символы (более конкретно, позиции) из исходной строки еще не используются.
|
|||
|
|
|||
|
Псевдокод будет выглядеть примерно так:
|
|||
|
```
|
|||
|
var str = ???;
|
|||
|
permAlone(current position in original string, characters used already in original string, created string) {
|
|||
|
if (current string is finished) {
|
|||
|
print current string;
|
|||
|
} else {
|
|||
|
for (var i = 0; i < str.length; i++) {
|
|||
|
if (str[i] has not been used) {
|
|||
|
put str[i] into the current position of new string;
|
|||
|
mark str[i] as used;
|
|||
|
permAlone(current position in original string, characters used already in original string, created string);
|
|||
|
remove str[i] as used because another branch in the tree for i + 1 will likely use it;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
permAlone(0, nothing used yet, empty new string (or array the same size as str));
|
|||
|
```
|
|||
|
|
|||
|
Другой способ подумать об этой проблеме - начать с пустого пространства. Введите первую букву в пространство. Это пространство теперь будет содержать первую подперемещение. Вот диаграмма, иллюстрирующая идею:
|
|||
|
|
|||
|

|
|||
|
|
|||
|
##### Нерекурсивный метод
|
|||
|
```
|
|||
|
// An approach to introduce a new character to a permutation
|
|||
|
var ch = '?';
|
|||
|
var source = ['?', '?', '?']; // Current sub-permutation
|
|||
|
var temp, dest = [];
|
|||
|
|
|||
|
for (var i = 0; i <= source.length; ++i) {
|
|||
|
temp = source.slice(0); // Copy the array
|
|||
|
temp.splice(i, 0, ch); // Insert the new character
|
|||
|
dest.push(temp); // Store the new sub-permutation
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
Затем поиск каждой перестановки можно было бы сделать нерекурсивно, включив вышеперечисленное в функцию, принимающую исходный массив и возвращающую целевой массив. Для каждой буквы входной строки передайте этот символ, а также массив, возвращенный из предыдущего вызова функции.
|
|||
|
|
|||
|
Способ визуализации этого заключается в рассмотрении дерева, которое начинается с первого символа вашей строки:
|
|||
|
|
|||
|

|
|||
|
|
|||
|
#### Связанные ссылки
|
|||
|
|
|||
|
* [Перестановки](https://www.mathsisfun.com/combinatorics/combinations-permutations.html)
|
|||
|
* [Алгоритм кучи](https://en.wikipedia.org/wiki/Heap%27s_algorithm)
|
|||
|
* Ресурсы JS Regex
|
|||
|
* [Объект JS String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)
|
|||
|
|
|||
|
##  Подсказка: 1
|
|||
|
|
|||
|
* Самый простой способ - использовать алгоритм Хипа для рекурсивного получения списка всех перестановок.
|
|||
|
|
|||
|
> _попытаться решить проблему сейчас_
|
|||
|
|
|||
|
##  Подсказка: 2
|
|||
|
|
|||
|
* После того, как у вас есть список, просто создайте регулярное выражение, чтобы поймать повторяющиеся символы.
|
|||
|
|
|||
|
> _попытаться решить проблему сейчас_
|
|||
|
|
|||
|
##  Подсказка: 3
|
|||
|
|
|||
|
* Вы захотите иметь перестановки в виде массива соединенных строк вместо отдельных символов.
|
|||
|
|
|||
|
> _попытаться решить проблему сейчас_
|
|||
|
|
|||
|
## Осторожно, спойлеры!
|
|||
|
|
|||
|

|
|||
|
|
|||
|
**Решение впереди!**
|
|||
|
|
|||
|
##  Решение базового кода:
|
|||
|
```
|
|||
|
function permAlone(str) {
|
|||
|
|
|||
|
// Create a regex to match repeated consecutive characters.
|
|||
|
var regex = /(.)\1+/g;
|
|||
|
|
|||
|
// Split the string into an array of characters.
|
|||
|
var arr = str.split('');
|
|||
|
var permutations = <a href='https://forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=3 ":rocket:"' target='_blank' rel='nofollow'>];
|
|||
|
var tmp;
|
|||
|
|
|||
|
// Return 0 if str contains same character.
|
|||
|
if (str.match(regex) !== null && str.match(regex)[0] === str) return 0;
|
|||
|
|
|||
|
// Function to swap variables' content.
|
|||
|
function swap(index1, index2) {
|
|||
|
tmp = arr[index1];
|
|||
|
arr[index1] = arr[index2];
|
|||
|
arr[index2] = tmp;
|
|||
|
}
|
|||
|
|
|||
|
// Generate arrays of permutations using the algorithm.
|
|||
|
function generate(int) {
|
|||
|
if (int === 1) {
|
|||
|
// Make sure to join the characters as we create the permutation arrays
|
|||
|
permutations.push(arr.join(''));
|
|||
|
} else {
|
|||
|
for (var i = 0; i != int; ++i) {
|
|||
|
generate(int - 1);
|
|||
|
swap(int % 2 ? 0 : i, int - 1);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
generate(arr.length);
|
|||
|
|
|||
|
// Filter the array of repeated permutations.
|
|||
|
var filtered = permutations.filter(function(string) {
|
|||
|
return !string.match(regex);
|
|||
|
});
|
|||
|
|
|||
|
// Return how many have no repetitions.
|
|||
|
return filtered.length;
|
|||
|
}
|
|||
|
|
|||
|
// Test here.
|
|||
|
permAlone('aab');
|
|||
|
```
|
|||
|
|
|||
|
 [Код запуска](https://repl.it/CLop/0)
|
|||
|
|
|||
|
### Код Объяснение:
|
|||
|
|
|||
|
* **regex** содержит регулярное выражение для соответствия повторяющимся последовательным символам.
|
|||
|
* Строка **str** разделяется на массив символов **arr** .
|
|||
|
* 0 возвращается, если **str** содержит одинаковые символы.
|
|||
|
* Функция `swap()` используется для замены содержимого двух переменных.
|
|||
|
* Следующий блок кода использует алгоритм Хипа для генерации массивов перестановок в **перестановках** .
|
|||
|
* **Отфильтрованная** переменная фильтрует **перестановки** для включения только непереписанных перестановок.
|
|||
|
* `filtered.length` возвращает количество полных перестановок предоставленной строки, которые не имеют повторяющихся последовательных букв.
|
|||
|
|
|||
|
#### Связанные ссылки
|
|||
|
|
|||
|
* [Разделение прототипа JS String](http://forum.freecodecamp.com/t/javascript-string-prototype-split/15944)
|
|||
|
* [Совместимость с JS String Prototype](http://forum.freecodecamp.com/t/javascript-string-prototype-match/15941)
|
|||
|
* [JS Array Prototype Push](http://forum.freecodecamp.com/t/javascript-array-prototype-push/14298)
|
|||
|
* [Присоединиться](http://forum.freecodecamp.com/t/javascript-array-prototype-join/14292)
|
|||
|
* [JS для пояснений](http://forum.freecodecamp.com/t/javascript-for-loop/14666s-Explained)
|
|||
|
* [array.length](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/length)
|
|||
|
* [Фильтр прототипов JS Array](http://forum.freecodecamp.com/t/javascript-array-prototype-filter/14289)
|
|||
|
|
|||
|
##  ПРИМЕЧАНИЯ ДЛЯ ВЗНОСОВ:
|
|||
|
|
|||
|
*  **НЕ** добавляйте решения, похожие на любые существующие решения. Если вы считаете, что это **_похоже, но лучше_** , попробуйте объединить (или заменить) существующее подобное решение.
|
|||
|
* Добавьте объяснение своего решения.
|
|||
|
* Классифицируйте решение в одной из следующих категорий - **Basic** , **Intermediate** и **Advanced** . 
|
|||
|
* Пожалуйста, добавьте свое имя пользователя, только если вы добавили **соответствующее основное содержимое** . (  **_НЕ_** _удаляйте существующие имена пользователей_ )
|
|||
|
|
|||
|
> Видеть  [**`Wiki Challenge Solution Template`**](http://forum.freecodecamp.com/t/algorithm-article-template/14272) для [**`Wiki Challenge Solution Template`**](http://forum.freecodecamp.com/t/algorithm-article-template/14272) для справки.
|