字符串字母的排列:如何删除重复的排列?

发布于 2024-11-27 11:03:52 字数 642 浏览 2 评论 0原文

这是一个打印字符串字符排列的标准函数:

void permute(char *a, int i, int n)
{
   int j;
   if (i == n)
     printf("%s\n", a);
   else
   {
        for (j = i; j < n; j++) //check till end of string
       {
          swap((a+i), (a+j));
          permute(a, i+1, n);
          swap((a+i), (a+j)); //backtrack
       }
   }
} 

void swap (char *x, char *y)
{
    char temp;
    temp = *x;
    *x = *y;
    *y = temp;
}

它工作正常,但有一个问题,它还会打印一些重复的排列,例如:

如果字符串是“AAB”,

则输出为:

AAB
ABA
AAB
ABA
BAA
BAA

这有 3 个重复条目出色地。

有办法防止这种情况发生吗?

——

谢谢

Alok Kr。

Here is a standard function to print the permutations of characters of a string:

void permute(char *a, int i, int n)
{
   int j;
   if (i == n)
     printf("%s\n", a);
   else
   {
        for (j = i; j < n; j++) //check till end of string
       {
          swap((a+i), (a+j));
          permute(a, i+1, n);
          swap((a+i), (a+j)); //backtrack
       }
   }
} 

void swap (char *x, char *y)
{
    char temp;
    temp = *x;
    *x = *y;
    *y = temp;
}

It works fine but there is a problem, it also prints some duplicate permutations, exapmle:

if string is "AAB"

the output is:

AAB
ABA
AAB
ABA
BAA
BAA

This is having 3 duplicate entries as well.

Can there be a way to prevent this to happen?

--

Thanks

Alok Kr.

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

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

发布评论

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

评论(10

救赎№ 2024-12-04 11:03:52

记下您之前交换的字符:

 char was[256];
 /*
 for(j = 0; j <= 255; j++)
    was[j] = 0;
 */
 bzero(was, 256);
 for (j = i; j <= n; j++)
 {
    if (!was[*(a+j)]) {
      swap((a+i), (a+j));
      permute(a, i+1, n);
      swap((a+i), (a+j)); //backtrack
      was[*(a+j)] = 1;
    }
 }

这必须是迄今为止条目中最快的一个,“AAAABBBCCD”(100 个循环)上的一些基准:

native C             - real    0m0.547s
STL next_permutation - real    0m2.141s

Take notes which chars you swapped previously:

 char was[256];
 /*
 for(j = 0; j <= 255; j++)
    was[j] = 0;
 */
 bzero(was, 256);
 for (j = i; j <= n; j++)
 {
    if (!was[*(a+j)]) {
      swap((a+i), (a+j));
      permute(a, i+1, n);
      swap((a+i), (a+j)); //backtrack
      was[*(a+j)] = 1;
    }
 }

This has to be the fastest one from the entries so far, some benchmark on a "AAAABBBCCD" (100 loops):

native C             - real    0m0.547s
STL next_permutation - real    0m2.141s
诗笺 2024-12-04 11:03:52

标准库有您需要的:

#include <algorithm>
#include <iostream>
#include <ostream>
#include <string>
using namespace std;

void print_all_permutations(const string& s)
{
    string s1 = s;
    sort(s1.begin(), s1.end()); 
    do {
        cout << s1 << endl;
    } while (next_permutation(s1.begin(), s1.end()));
}

int main()
{
    print_all_permutations("AAB");
}

结果:

$ ./a.out
AAB
ABA
BAA

Standard library has what you need:

#include <algorithm>
#include <iostream>
#include <ostream>
#include <string>
using namespace std;

void print_all_permutations(const string& s)
{
    string s1 = s;
    sort(s1.begin(), s1.end()); 
    do {
        cout << s1 << endl;
    } while (next_permutation(s1.begin(), s1.end()));
}

int main()
{
    print_all_permutations("AAB");
}

Result:

$ ./a.out
AAB
ABA
BAA
浴红衣 2024-12-04 11:03:52

另一种方法可能是:

  1. 对数组进行预排序。

  2. 这将确保所有重复项现在都是连续的。

  3. 所以,我们只需要查看我们修复的前一个元素(并排列其他元素)

  4. 如果当前元素与前一个元素相同,不排列。

Another approach could be:

  1. Presort the array.

  2. This will ensure that all duplicate are now consecutive.

  3. So, we just need to see the previous element which we we fixed (and permuted others)

  4. if current element is same as previous, don't permute.

情深如许 2024-12-04 11:03:52

我将按照以下方式执行此操作:首先,我生成字符“组”(即 AABBBC 生成两个组:(AA) 和 (BBB) 和 (C)

首先,我们将 AA 的所有分布迭代到 n 字符上。对于找到的每个分布,我们将 BBB 的所有分布迭代到 n 上。 code>n-2 剩余字符(不对于涉及 AB 的每个分布,我们迭代 C< 的所有分布。 /code> 到剩余的空闲字符位置。

I would do it the following way: First, I generate "groups" of characters (i.e. AABBBC yields two groups: (AA) and (BBB) and (C).

First, we iterate over all distributions of AA onto the n characters. For each distribution found, we iterate over all distributions of BBB onto the n-2 remaining characters (not occupied by an A). For each of these distributions involving As and Bs, we iterate over all distributions of C onto the remaining free character positions.

情深缘浅 2024-12-04 11:03:52

您可以使用 std::set 来确保结果的唯一性。也就是说,如果它是 C++(因为你这样标记它)。

否则 - 手动浏览结果列表并删除重复项。

当然,您必须保存结果并对其进行后处理,而不是像现在一样立即打印。

You can use std::set to ensure uniqueness of the results. That is if it is C++ (because you tagged it as such).

Otherwise - go through the list of the results manually and remove duplicates.

You'll have to save the results and post-process them of course, not print immediately as you do now.

寄风 2024-12-04 11:03:52

如果您只是认为这是一个需要存储所有排列以供将来使用的问题,那就非常简单了。

所以你将有一个排列字符串的数组。

现在考虑一个新问题,这也是一个标准问题,您需要从数组中删除重复项。

我希望这有帮助。

It would quite simple if you just think it as a problem where you need to store all the permutations for some future use.

SO you'll have an array of permuted strings.

Now think of a new problem, which is also an standard one where you need to remove the duplicates from array.

I hope that helps.

高跟鞋的旋律 2024-12-04 11:03:52

@Kumar,我认为你想要的是如下所示的内容:

#include <stdio.h>
#include <string.h>

/* print all unique permutations of some text. */
void permute(int offset, int* offsets, const char* text, int text_size)
{
    int i;

    if (offset < text_size) {
            char c;
            int j;

            /* iterate over all possible digit offsets. */
            for (i=0; i < text_size; i++) {
                    c=text[i];
                    /* ignore if an offset further left points to our
                       location or to the right, with an identical digit.
                       This avoids duplicates. */
                    for (j=0; j < offset; j++) {
                            if ((offsets[j] >= i) &&
                                (text[offsets[j]] == c)) {
                                    break;
                            }
                    }

                    /* nothing found. */
                    if (j == offset) {
                            /* remember current offset. */
                            offsets[offset]=i;
                            /* permute remaining text. */
                            permute(offset+1, offsets, text, text_size);
                    }
            }
    } else {
            /* print current permutation. */
            for (i=0; i < text_size; i++) {
                    fputc(text[offsets[i]], stdout);
            }
            fputc('\n', stdout);
    }
}

int main(int argc, char* argv[])
{
    int i, offsets[1024];

    /* print permutations of all arguments. */
    for (i=1; i < argc; i++) {
            permute(0, offsets, argv[i], strlen(argv[i]));
    }

    return 0;
}

根据要求,此代码是 C 代码,它非常快并且可以执行你想要的操作。当然,它包含可能的缓冲区溢出,因为偏移缓冲区具有固定大小,但这只是一个示例,对吗?

编辑:有人尝试过吗?有没有更简单或更快的解决方案?令人失望的是没有人进一步评论!

@Kumar, I think what you want is something like the following:

#include <stdio.h>
#include <string.h>

/* print all unique permutations of some text. */
void permute(int offset, int* offsets, const char* text, int text_size)
{
    int i;

    if (offset < text_size) {
            char c;
            int j;

            /* iterate over all possible digit offsets. */
            for (i=0; i < text_size; i++) {
                    c=text[i];
                    /* ignore if an offset further left points to our
                       location or to the right, with an identical digit.
                       This avoids duplicates. */
                    for (j=0; j < offset; j++) {
                            if ((offsets[j] >= i) &&
                                (text[offsets[j]] == c)) {
                                    break;
                            }
                    }

                    /* nothing found. */
                    if (j == offset) {
                            /* remember current offset. */
                            offsets[offset]=i;
                            /* permute remaining text. */
                            permute(offset+1, offsets, text, text_size);
                    }
            }
    } else {
            /* print current permutation. */
            for (i=0; i < text_size; i++) {
                    fputc(text[offsets[i]], stdout);
            }
            fputc('\n', stdout);
    }
}

int main(int argc, char* argv[])
{
    int i, offsets[1024];

    /* print permutations of all arguments. */
    for (i=1; i < argc; i++) {
            permute(0, offsets, argv[i], strlen(argv[i]));
    }

    return 0;
}

This code is C, as requested, it's pretty fast and does what you want. Of course it contains a possible buffer overflow because the offset buffer has a fixed size, but this is just an example, right?

EDIT: Did anyone try this out? Is there a simpler or faster solution? It's disappointing noone commented any further!

白首有我共你 2024-12-04 11:03:52
void permute(string set, string prefix = ""){
    if(set.length() == 1){
            cout<<"\n"<<prefix<<set;
    }
    else{
            for(int i=0; i<set.length(); i++){
                    string new_prefix = prefix;
                    new_prefix.append(&set[i], 1);
                    string new_set = set;
                    new_set.erase(i, 1);
                    permute(new_set, new_prefix);
            }
    }
}

只需将其用作 permute("word");

void permute(string set, string prefix = ""){
    if(set.length() == 1){
            cout<<"\n"<<prefix<<set;
    }
    else{
            for(int i=0; i<set.length(); i++){
                    string new_prefix = prefix;
                    new_prefix.append(&set[i], 1);
                    string new_set = set;
                    new_set.erase(i, 1);
                    permute(new_set, new_prefix);
            }
    }
}

And simply use it as permute("word");

愁以何悠 2024-12-04 11:03:52

不要在字符串的不同位置对相同字符进行排列。

在Python中:

def unique_permutation(a, l, r):
    if l == r:
        print ''.join(a)
        return
    for i in range(l, r+1):
        if i != l and a[i] == a[l]:
            continue
        a[i], a[l] = a[l], a[i]
        unique_permutation(a, l+1, r)
        a[i], a[l] = a[l], a[i]

Do not permute for same character at different position of the string.

In Python:

def unique_permutation(a, l, r):
    if l == r:
        print ''.join(a)
        return
    for i in range(l, r+1):
        if i != l and a[i] == a[l]:
            continue
        a[i], a[l] = a[l], a[i]
        unique_permutation(a, l+1, r)
        a[i], a[l] = a[l], a[i]
雨轻弹 2024-12-04 11:03:52

算法步骤:

  1. 将给定的字符串存储到临时字符串中,例如“temp”,
  2. 从临时字符串中删除重复项
  3. ,最后调用“void permute(char *a, int i, int n)”函数来打印给定字符串的所有排列,没有重复项,

我认为,这是最好、最有效的解决方案。

Algorithm steps:

  1. Store the given string into temporary string say "temp"
  2. Remove duplicates from temp string
  3. And finally call "void permute(char *a, int i, int n)" function to print all permutation of given string without duplicates

I think, this is best and efficient solution.

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