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

发布于 2024-12-24 21:07:32 字数 591 浏览 1 评论 0 原文

我有一个整数数组 1<=N<=100,如何获得该数组的排列?数组可能包含重复项,因此排列的结果集可能是重复的,因此需要获取所有非重复排列。

  • 我发现很多片段可以将 int[] 转换为字符串并执行排列和打印输出,但正如我所见,这里是范围 1<=N<=100 的整数code>,因此将它们转换为字符串会破坏整数。
  • 我可以获得具有重复项的所有排列,包括对于删除重复项的最终一组排列,必须相互检查以删除重复项等等,这是一个繁重的过程。

有没有更简单的方法?

例如,123 将给出:

231
321
312
132
213
123

类似地,对于 112 程序将给出:

121
211
211
121
112
112

因此,对于 n 元素集,排列将是 n! 如果元素中有重复项,则会减少 tht。 我问如何删除那些重复的集。 (排列 arr[] 的重复集)

I have an array of integers 1<=N<=100, How can I get permutations of this array? Array may contain duplicates, so resulting set of permutations can be duplicate, so need to get all non-duplicate permutations.

  • I've found lot of snippets which would convert the int[] to string and perform permutations and printout, but as I hv here is integers of range 1<=N<=100, so converting them into string would spoil integer.
  • I can get all permutations with duplicates including, for final set of permutations where duplicates are removed have to check with each other to remove a duplicate or so, it so heavy process.

Is there any simpler way?

For example, 123 would give:

231
321
312
132
213
123

Similarly for 112 program would give:

121
211
211
121
112
112

So, for n-set of elements, permutations will be of n!
With duplicates in elements, would decrease tht.
I'm asking how can I remove those duplicate sets. (duplicate set of permutation arr[])

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

睡美人的小仙女 2024-12-31 21:07:32

如果首先对元素进行词法排序是可以接受的,那么您就可以进行词法排列。包括一个对 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] 开始,您不再获得排列(与上面的示例相比)。

If it is acceptable to first sort the elements lexically, then you can your lexical permutation. Including an algorithm which does it for an array of int, easily modifiable to strings.

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;
}

Example of how to use it

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

Using this with [1,2,3] you get

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

with [1,1,3] you instead get

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

which is what you asked for I think.

Since the method retunes the "next" permutation in lexicographically order it is important that the elements are ordered. Starting with [3, 2, 1] you get no more permutations (compare to example above).

我不吻晚风 2024-12-31 21:07:32

您可以使用 Set 而不是整数数组,它可以自动删除您的重复项。

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

You could use a Set instead of an array of ints, it could delete your duplications automatic.

Edit: @allingeek give me an idea. More than implements your own Set you could write a wrapper over an int and overwrite your equals and hashcode methods, finding the way where your permutations are equals. Perhaps using the numbers in order and others advise given in "Effective Java" (for equals and hashcode implementations to avoid mistakes). It could give you a better way to find your permutations in the Set. More than use expressions language as I say at first.

饮惑 2024-12-31 21:07:32

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

您的问题基本上是字母表的选择问题(1 <= N <= 100)。如果您想选择其中的 5 个或 500 个,都没关系,您想选择某个数字,称之为 x。想想您想要从中选择的独特元素,以及那些您不想重复的元素(这可能是您的字母表的适当子集,也可能不是)。将这些元素排成一行。该行的长度为n。现在,可以如下解决枚举 x 的选择的选择问题。想象一个 n 位数字,它只能包含 nx 个零。要获得这个 x 级数字,只需从 0 开始,枚举最多 2**n 的所有可能数字,仅选择那些恰好具有 x 个 1(和 nx 个零)的数字。然后,这些 1 从字母表的 n 个位置中选择 x 个位置,每个 x 级数字都会为您选择一个排列。

如果有人知道一种优化方法,这样您就不必计算出所有非 x 级的优化,请说出来。
编辑:
答案似乎就在这里

You want all non-duplicate permutations of an array. The number of these, assuming each array entry is unique, Factorial(array.length), quickly becomes uncomputably large. But assuming you want to enumerate them the simplest way is to do the following :

Your problem is basically a selection problem over your alphabet (1 <= N <= 100). It does not matter if you want to select 5 of these or 500, you want to select some number, call it, x. Think of the unique elements you want to select from, those that you do not want to duplicate (this may be a proper subset of your alphabet, or not). Lay these elements out in a row. The length of this row is n. Now the selection problem of enumerating a selection of x of these can be solved as follows. Think of an n bit number, that can only ever contain n-x zeroes. To get this rank-x number, simply start from 0 and enumerate all possible numbers up to 2**n, selecting only those that have exactly x 1s (and n-x zeroes). These 1s then select x positions from the n positions of your alphabet, and each of these rank-x numbers selects a permutation for you.

If anyone knows an optimization so that you don't have to work out all the non-rank-x ones, please say so.
EDIT:
The answer, it seems, is here

葮薆情 2024-12-31 21:07:32

删除重复元素的最简单方法是将内容添加到 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);

The easiest method to remove duplicate elements is to add the contents to a Set which won't allow duplicates and then add the Set back to an ArrayList as an example below.

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);
染柒℉ 2024-12-31 21:07:32
  1. 对数组进行排序。
  2. 使用嵌套循环,其中外循环迭代数组中的每个元素。如果下一个元素与上一个元素具有相同的值,则跳过。然后,内部循环将该元素放置在列表中的每个位置。在每个循环上保存排列。

这将生成排列并跳过重复的排列。

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;
}

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

  1. Sort the array.
  2. Use a nested loop where the outer loop iterates through each element in the array. If the next element has the same value as the last, skip. The inner loop then places that element at each position in the list. Saving a permutation on each loop.

This will generate the permutations as well as skip repetitious permutations.

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;
}

EDIT: Actually I think this would need to be tweaked a bit more to capture the last few cases where duplicates are generated. That would be where a repeated element is inserted next to its same value. I've changed the code appropriately.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文