获取int []的排列删除重复集

时间:2012-01-04 19:35:07

标签: java permutation

我有一个[]的整数1< = N< = 100,我怎么能得到这个数组的排列? - >数组可能包含重复项,因此得到的排列集可能是重复的,因此需要获得所有非重复的排列。

  • 我找到了很多将int []转换为字符串的片段 并执行排列和打印输出,但我在这里是整数 范围1< = N< = 100,因此将它们转换成字符串会破坏 整数。
  • 我可以获得所有重复的排列,包括最终的排列 移除重复项的排列集必须检查
    彼此删除一个副本,它是如此繁重的过程。

有没有更简单的方法?

例如:123会给出

231
321
312
132
213
123

同样对于112计划会给出

121
211
211
121
112
112

因此,对于n组元素,排列将为n!  随着元素的重复,会减少, 我问我怎样才能删除那些重复的集合。 (重复的置换集arr [])

5 个答案:

答案 0 :(得分:6)

如果首先对词素进行词法排序是可以接受的,那么你就可以进行词汇排列。包括为int数组执行的算法,可以轻松修改为字符串。

public static boolean permuteLexically(int[] data) {
    int k = data.length - 2;
    while (data[k] >= data[k + 1]) {
        k--;
        if (k < 0) {
            return false;
        }
    }
    int l = data.length - 1;
    while (data[k] >= data[l]) {
        l--;
    }
    swap(data, k, l);
    int length = data.length - (k + 1);
    for (int i = 0; i < length / 2; i++) {
        swap(data, k + 1 + i, data.length - i - 1);
    }
    return true;
}

如何使用它的示例

public static void main(String[] args) {
    int[] data = { 1,2,3 };
    do {
        System.err.println(Arrays.toString(data));
    } while(Util.permuteLexically(data));
}

与[1,2,3]一起使用

[1, 2, 3]
[1, 3, 2]
[2, 1, 3]
[2, 3, 1]
[3, 1, 2]
[3, 2, 1]

用[1,1,3]代替

[1, 1, 3]
[1, 3, 1]
[3, 1, 1]

这就是我想的那个。

由于该方法以字典顺序重新调整“下一个”排列,因此重要的是对元素进行排序。从[3,2,1]开始,您不再获得排列(与上面的示例相比)。

答案 1 :(得分:3)

您可以使用Set代替 ints数组,它可以自动删除您的重复。

编辑: @allingeek给我一个主意。除了实现你自己的Set之外,你可以在int上编写一个包装器并覆盖你的equals和hashcode方法,找到你的排列等于的方式。也许按顺序使用数字和其他人在“Effective Java”中给出建议(对于equals和hashcode实现以避免错误)。它可以为您提供更好的方法来查找Set中的排列。不像我刚开始说的那样使用表达式语言。

答案 2 :(得分:2)

您需要数组的所有非重复排列。假设每个数组条目都是唯一的,Factorial(array.length),它们的数量很快变得不可复制。但假设您想要枚举它们,最简单的方法是执行以下操作:

您的问题基本上是您的字母表中的选择问题(1 <= N <= 100)。如果您想要选择其中的5个或500个无关紧要,您想要选择一些数字,将其称为x。想想你想要选择的独特元素,那些你不想复制的元素(这可能是你的字母表的合适子集,或者不是)。将这些元素排成一行。这一行的长度是n。现在,列举这些x的选择的选择问题可以如下解决。想想一个n位数,它只能包含n-x个零。要获得此rank-x数,只需从0开始并枚举所有可能的数字,最多为2 ** n,仅选择那些具有x 1s(和n-x个零)的数字。这些1然后从您的字母表的n个位置选择x个位置,并且这些rank-x数字中的每一个都为您选择一个排列。

如果有人知道优化,那么你就不必计算所有非rank-x的优化,请说明。 编辑: 答案似乎是here

答案 3 :(得分:1)

删除重复元素的最简单方法是将内容添加到Set,这不允许重复,然后将Set添加回ArrayList作为示例。

ArrayList<String>al=new ArrayList<String>();

al.add(String.valueOf(arr[0]));  //Just as an example.

HashSet hs = new HashSet();
hs.addAll(al);
al.clear();
al.addAll(hs);

答案 4 :(得分:1)

  1. 对数组进行排序。
  2. 使用嵌套循环,其中外部循环遍历数组中的每个元素。如果下一个元素与最后一个元素具有相同的值,则跳过。然后内部循环将该元素放置在列表中的每个位置。在每个循环中保存排列。
  3. 这将生成排列并跳过重复的排列。

    int[] sortedSourceArray = ...;
    int last = -1;
    int current = -1;
    // build one permutation with the original array
    buildPermutation(permutationList, sortedSourceArray);  // I'm not going to implement this for you.
    for (int i = 0; i < sortedSourceArray.length; i++) {
      current = sortedSourceArray[i];
      // check if the new value is the same as the last
      if(current == last) 
        continue;
      // remove the current element from the list
      // build your permutations
      for(int j = 0; j < sortedSourceArray.length; j++) {
        // skip if its inserting the element at its original position
        if(j == i)
          continue;
        // fix the duplicates for blocks of repeated elements
        if(j < sortedSourceArray.length-1 && sortedSourceArray[j+1] == current)
          continue;
        // inject the current element at the new position
        inject(sortedSourceArray, current, j); 
        // build the permutation
        buildPermutation(permutationList, sortedSourceArray);
        // remove the current element from that position
        remove(sortedSourceArray, j);
      }
      last = current;
    }
    

    编辑:实际上我认为需要进一步调整以捕获生成重复项的最后几种情况。这将是重复元素插入其相同值旁边的位置。我已经适当地更改了代码。