R

E

A

C

T

O

xamples 

epeat

ode

pproach

ptimize

est

{String Permutations}

The Challenge

Given a string, return an array of all the permutations of that string.

All permutations must be the same length as the original string but do not need to be real words.


stringPermutations('one') //should return  [ 'eon', 'eno' 'neo', 'noe', 'one', 'oen']
stringPermutations('app') //should return  [ 'app','pap','ppa']
stringPermutations('nn') //should return  [ 'nn' ]

Notes

  • The  returned array should contain only unique values
  • The returned array should be alphabetically sorted

Approach

A string of one character has one permutation

'a'   ->   [ 'a' ]

For each additional letter, add it to each possible space in the current results

stringPermutations('abc')

insert 'a'

[ 'a' ]

Approach

A string of one character has one permutation

'a'   ->   [ 'a' ]

For each additional letter, add it to each possible space in the current results

stringPermutations('abc')

insert 'b'

'b'

[           'a'          ]

   'ab'        ]

[       'ba

Approach

For each additional letter, add it to each possible space in the current results

stringPermutations('abc')

 

'c'

 [        'ba',            'ab'        ]

insert 'c'

[  'cba', 'bca', 'bac'

      'cab', 'acb', 'abc  ]

Possible ITERATIVE Solution


function stringPermutations(str) {
  let permutations = [];
  const letters = str.split('');

  permutations.push([letters.shift()]) // Adds first letter (as a subarray) to `permutations`

  while (letters.length) {
    const nextLetter = letters.shift(); // Takes the next potential letter off the `letters` array
    const tempermutations = []; // Temporary list of permutated results

    permutations.forEach(currentPerm => { // For each permutation in progress

      for (let i = 0; i <= currentPerm.length; ++i) { // As long as the letters already processed
        const currentCopy = Array.from(currentPerm); // Copy `currentPerm` to prep for mutation

        // Add `nextLetter` at each possible position during each iteration of the `for` loop
        currentCopy.splice(i, 0, nextLetter)

        // Add the mutated copy to the temporary list of permutations
        tempermutations.push(currentCopy);
      }
    });

    // Overwrite previous permutations which are now one letter short
    permutations = tempermutations;
  }

  // Turn each permutated subarray back into a string
  permutations = permutations.map(wordArr => wordArr.join(''));

  // Filter out non-unique permutations, sort the array into alphabetical order, then return
  return permutations.filter((el, idx) => permutations.indexOf(el) === idx).sort();
}

Possible  Recursive Solution

// Adapted from: http://www.thatjsdude.com/interview/js1.html#permutation

function permutations(str){
  // Convert `str` to an array
  const arr = str.split(''),
    len = arr.length, 
    perms = [];
  let rest,
    picked,
    restPerms,
    next;
  
  // BASE CASE: If there are no 'rest' characters left, return `['']`
  if (len === 0) return [str];

  for (let i = 0; i < len; ++i) {

    // Create an array copy of all letters in current order
    rest = Object.create(arr);  // Other options include `.slice` and `Array.from` methods
    // Remove & reserve the 1st letter whilst we permute the rest
    picked = rest.splice(i, 1);

    // Create the permuted string variations recursively
    restPerms = permutations(rest.join(''));

    for (let k = 0, kLen = restPerms.length; k < kLen; ++k) {
      // Concatenate each variation of the 'rest' letters to the reserved letter
      next = picked.concat(restPerms[k]);
      // Push each variation into the permutations list
      perms.push(next.join(''));
    }
  }
  
  // Filter out non-unique permutations, sort the array into alphabetical order, then return
  return perms.filter((el, idx) => perms.indexOf(el) === idx).sort();
}

Possible  Recursive Solution Variation

// Adapted from Galen Corey's 1610GHA Solution

function getPerms(lettArray){
  let perms = [];

  // BASE CASE: If we're on the last letter return the letter
  if (lettArray.length === 1) return lettArray;

  lettArray.forEach((char, idx) => {
    // Make a copy of the current array;
    const rest = lettArray.slice();

    // Remove the idx-th character (`char`) in the array
    rest.splice(idx, 1);

    // Recursively concatenate the 'rest' variations to the current character
    const subPerms = getPerms(rest).map(subPerm => char + subPerm);

    // Concatenate all the new permutations into the `perms` array
    perms = [...perms, ...subPerms];
  })

  return perms
}

function getPermsWrapper(str){
    // Turn the input string into an array and call `getPerms` on it
    const allPerms = getPerms(str.split(''));

    // Filter out repeats and sort into alphabetical order
    return allPerms.filter((word, idx) => allPerms.indexOf(word) === idx).sort();
}

Possible  Recursive Solution Variation 2

// Adapted from Griffin Telljohann's Code Wars solution

function permutations(str) {
  if (!str.length) { return ['']; }
  
  // Split the input string and map over each character
  const initial =  str.split('').map((char, idx, arr) => {
    // Recursively create permutations of each string minus the selected `char`acter
    const subPermutations = permutations(remove(arr, char).join(''))
    
    // Map over each subPermutation and return that with the selected `char`acter appended to it
    return subPermutations.map(str => char + str);
  }).reduce((prev, curr) => prev.concat(curr), [])  // Concatenate each new array of permutations to the previous one
  return removeDuplicates(initial);  // Filter out the dupes, sort, and return
}


// Takes an array and a `char`acter and returns it without said `char`acter
function remove(arr, char) {
  const idx = arr.indexOf(char);
  return [...arr.slice(0, idx), ...arr.slice(idx + 1)];
}


// Filters out dupes and sorts in alphabetical order
function removeDuplicates(arr) {
  return arr.filter((el, idx) => arr.indexOf(el) === idx).sort();
}

Conclusion

Know your string and array methods.

 

Consider breaking a problem into smaller pieces.

String Permutations

By tessaslides

String Permutations

Technical interview problem on generating string permutations

  • 1,118