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) для справки.
 |