排列过滤,没有重复的字符

时间:2017-06-07 13:29:44

标签: javascript filter permutation

这是来自freeCodeCamp的任务。

我的目标是创建一个功能:

  1. 带任何字符串。
  2. 创建一个数组,其中包含该字符串中可能存在的所有排列。
  3. 过滤数组并仅返回不重复连续字母的字符串。
  4.   

    返回所提供的字符串的总排列数,这些字符串不会重复连续的字母。假设所有人物都在   提供的字符串都是唯一的。例如,aab应该返回2   因为它总共有6个排列(aab,aab,aba,aba,baa,baa),   但其中只有2个(aba和aba)没有相同的字母(在此   案例a)重复。

    我无法弄清楚我写错了什么。我认为问题在于过滤功能或排列列表有问题。

    function permAlone(str) {
    
        if (str.length == 1) {
            return str;
        }
        // Creates all possible Permutations and pushes to an array 
        var arr = [];
        var p = 0; // position of the element which needs to be swapped
        // Loop count equal to number of Permutations.
        var loops = factorialize(str.length);
        for (var i = 0; i < loops; i++) {
    
            // if the position is not the last element in the strig keep swapping with next following character
    
            if (p != str.length - 1) {
                var splitStr = str.split('')
                arraySwapElements(splitStr, p, p + 1);
                str = splitStr.join('');
                arr.push(str);
                p += 1;
                // when position is at the last index, change position to 0
            } else {
                p = 0;
                i -= 1;
            }
        }
    
        // swaps 2 items in an array
    
        function arraySwapElements(arr, a, b) {
            var item = arr[a];
            arr[a] = arr[b];
            arr[b] = item;
        };
    
    
        // outputs a factorial of a number
    
        function factorialize(num) {
            if (num === 0) {
                return 1;
            } else {
                return num * factorialize(num - 1);
            }
        }
    
        // filters any array which has 2 or more repeating characters
    
        var x = arr.filter(function(str) {
            var re = /(.)\1+/;
            var result = re.test(str);
            if (!result) {
                return str;
            }
        })
    
        // returns the filtered arrays length
        return x.length
    
    
    
    }
    
    console.log(permAlone('abfdefa'));
    

    测试时:

    permAlone("aab") should return a number. // Correct
    permAlone("aab") should return 2.  // Correct
    permAlone("aaa") should return 0. // Correct
    permAlone("aabb") should return 8. // Correct
    permAlone("zzzzzzzz") should return 0.// Correct
    permAlone("a") should return 1.// Correct
    permAlone("aaab") should return 0.// Correct
    
    permAlone("abcdefa") should return 3600. // Incorrect
    permAlone("abfdefa") should return 2640.// Incorrect
    permAlone("aaabb") should return 12. // Incorrect
    

1 个答案:

答案 0 :(得分:1)

The issue stems from the logic used in the for loop. While the loop does generate the right number of total permutations, it doesn't generate all permutations.

For example, if our string to be permuted was "abcd", the swapping mechanism would generate strings like this:

bacd bcad bcda

cbda cdba cdab

dcab dacb dabc

adbc abdc abcd

Uh oh! That last arrangement is the same as the starting string. When we start swapping again, we're going to get the same set that we did on the first pass. We're never going to get a permutation like "acbd". Thus the resulting array contains higher numbers of some permutations and lower numbers of others.

I'm not sure how to fix it with the approach you're using, but a recursive function to get permutations could be written like this:

// Returns an array of all permutations of a string
function getPerms(str) {
  // Base case. If the string has only one element, it has only one permutation.
  if (str.length == 1) {
    return [str];
  }
  // Initialise array for storing permutations
  let permutations = [];
  // We want to find the permutations starting with each character of the string
  for (let i = 0; i < str.length; i++) {
    // Split the string to an array
    let splitStr = str.split('');
    // Pull out the character we're checking for permutations starting with
    let currentElem = splitStr.splice(i, 1)[0];
    // Get permutations of the remaining characters
    let subPerms = getPerms(splitStr.join(''));
    // Concat each of these permutations with the character we're checking
    // Add them to our list
    subPerms.forEach(function (combination) {
      permutations.push(currentElem.concat(combination));
    });
  }
  // return our list
  return combinations;
}