[英]Permutation of String letters: How to remove repeated permutations?
這是打印字符串字符排列的標准函數:
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;
}
它工作正常,但有一個問題,它還打印一些重復的排列,exapmle:
如果字符串是“AAB”
輸出是:
AAB
ABA
AAB
ABA
BAA
BAA
這也有3個重復的條目。
有沒有辦法防止這種情況發生?
-
謝謝
Alok Kr。
記下您之前交換過的字符:
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
另一種方法可能是:
預先排列陣列。
這將確保所有重復現在都是連續的。
所以,我們只需要查看我們修復的前一個元素(並置換其他元素)
如果當前元素與之前的元素相同,則不要置換。
標准庫可滿足您的需求:
#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
我會這樣做:首先,我生成“組”字符(即AABBBC
產生兩組: (AA) and (BBB) and (C)
。
首先,我們將AA
所有分布迭代到n
字符上。 對於找到的每個分布,我們將BBB
所有分布迭代到剩余的n-2
字符(未被A
占用)。 對於涉及A
s和B
s的這些分布中的每A
,我們將C
所有分布迭代到剩余的自由字符位置上。
您可以使用std::set
來確保結果的唯一性。 那就是它是C ++(因為你這樣標記它)。
否則 - 手動瀏覽結果列表並刪除重復項。
您必須保存結果並對其進行后處理,而不是像現在那樣立即打印。
如果您認為這是一個需要存儲所有排列以供將來使用的問題,那將非常簡單。
所以你將擁有一系列置換字符串。
現在想一個新問題,這也是一個標准的問題,你需要從數組中刪除重復項。
我希望有所幫助。
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);
}
}
}
只需將其用作置換(“單詞”);
不要在string
不同位置置換相同的字符。
在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]
@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,根據要求,它非常快,可以滿足您的需求。 當然它包含一個可能的緩沖區溢出,因為偏移緩沖區有一個固定的大小,但這只是一個例子,對吧?
編輯:有沒有人試過這個? 有更簡單或更快的解決方案嗎? 令人失望的是沒有人評論任何進一步的評論!
算法步驟:
我認為,這是最好,最有效的解決方案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.