为什么我的代码会推动每个排列两次?

时间:2017-01-20 18:58:18

标签: javascript algorithm

我很困惑为什么我的代码推动每次排列两次。请有人帮忙。我正在使用堆的算法:

var regex = /(.)\1+/g;

function permAlone(str) {
  var newArray = str.split('');
  var n = newArray.length;
  var permutations = [];
  var tmp;

  function swap(index1, index2) {
    tmp = newArray[index1];
    newArray[index1] = newArray[index2];
    newArray[index2] = tmp;
  }

  function generate(n, newArray) {
    if (n === 1) {
      permutations.push(newArray.join(''));
    } else {
      for(var i = 0; i<n-1; i++) {
        generate(n-1, newArray);
        swap(n % 2 ? 0 : i, n-1);
        permutations.push(newArray.join(''));
      }

      generate(n-1, newArray);
    }      
  }  

  generate(n, newArray);
  return permutations;
}    

permAlone('aab');

返回的数组是:

["aab", "aab", "aab", "baa", "baa", "aba", "aba", "aba", "baa", "baa"]

正如您所看到的,排列的出现次数远远多于每种事物的预期。任何帮助都会很棒

2 个答案:

答案 0 :(得分:1)

代码有点复杂,并且在给定递归的情况下很难跟踪,但如果你想要的只是一个只有唯一值的数组,你可以简单地将以下代码应用于结果数组:

 function stripDuplicates(input) {
     if (!input || typeof(input) !== 'object' || !('length' in input)) {
         throw new Error('input argument is not array.');
     }

     var newArray = [];
     for (var i = 0; i < input.length; i++) {
         if (newArray.indexOf(input[i]) === -1) {
             newArray.push(input[i]);
         }
     }

     return newArray;
 }

这也可以在功能上而不是在命令式上完成,但这更像是一种偏好,而不是优化问题。

Bálint还指出,您只能将结果转换为Set,然后将Set转换回Array,这会自动删除任何重复项。但要注意,Set是Javascript中相对较新的功能,并且不会在ES6之前的环境中运行。

答案 1 :(得分:0)

您可以致电:

permutations.push(newArray.join(''));
你的for循环内部。那应该不存在。然后,当然,如果你正在排列具有重复字符的字符串,那么,期望看到欺骗。例如,如果您置换字符串“aa”,您将从此算法“aa”和“aa”中获得两个条目。 Heap的算法不会尝试删除欺骗,它会将每个元素视为字符串中的唯一元素。显然,使用删除欺骗是微不足道的,如果这是你关心的事情。