Распечатайте все перестановки строки в C
Я изучаю backtracking и recursion, и я застрял в алгоритме для печати всех перестановок строки. Я решил это, используя алгоритм для перестановки, но я не могу понять метод рекурсии. Я искал в Интернете и нашел этот код:
void permute(char *a, int i, int n)
{
int j;
if (i == n)
printf("%s\n", a);
else
{
for (j = i; j <= n; j++)
{
swap((a+i), (a+j));
permute(a, i+1, n);
swap((a+i), (a+j));
}
}
}
Как работает этот алгоритм, который я не могу понять? Я даже пробовал сухую работу!
Как применяется обратное отслеживание?
И эффективнее ли алгоритм Белла для вычисления перестановки?
Ответы
Ответ 1
Алгоритм в основном работает над этой логикой:
Все перестановки строки X - это то же самое, что и все перестановки каждого возможного символа в X, в сочетании со всеми перестановками строки X без этой буквы в ней.
То есть все перестановки "abcd"
- "a", связанный со всеми перестановками "bcd"
- "b", связанный со всеми перестановками "acd"
- "c", связанный со всеми перестановками "bad"
- "d", связанный со всеми перестановками "bca"
Этот алгоритм, в частности, вместо выполнения рекурсии на подстроках, выполняет рекурсию на входной строке, не используя дополнительной памяти для выделения подстрок. "Откат" отменяет изменения в строке, оставляя ее в исходном состоянии.
Ответ 2
В коде есть 2 проблемы, связанные с n
, предполагаемая длина строки. Код for (j = i; j <= n; j++) { swap((a+i), (a+j)); ...
свопит в строку нулевой символ '\0'
и дает усеченные результаты кода. Проверьте оригинал (i == n)
, который должен быть (i == (n-1))
.
Откат применяется, вызывая swap()
дважды эффективно отменяя его первоначальный своп.
Порядок сложности для алгоритма Белла одинаковый.
#include <stdio.h>
void swap(char *a, char *b) { char t = *a; *a = *b; *b = t; }
void permute(char *a, int i, int n) {
// If we are at the last letter, print it
if (i == (n-1)) printf("%s\n", a);
else {
// Show all the permutations with the first i-1 letters fixed and
// swapping the i'th letter for each of the remaining ones.
for (int j = i; j < n; j++) {
swap((a+i), (a+j));
permute(a, i+1, n);
swap((a+i), (a+j));
}
}
}
char s[100];
strcpy(s, "ABCD");
permute(s, 0, strlen(s));
Ответ 3
Код, который вы нашли, правильный! Алгоритм меняет текущий символ в строке со всеми последующими символами и рекурсивно вызывает функцию. Его трудно объяснить словами. Приведенный ниже рисунок может вам помочь.
Откат выполняется во втором свопе для изменения эффекта 1-го свопа, т.е. мы возвращаемся к исходной строке и теперь будем менять следующий символ в массиве с текущим символом. Временная сложность алгоритма. O (n * n!), так как цикл выполняется n раз, а функция перестановок называется n! раз. (Для 1-й итерации ее называют n раз, для второй итерации (n-1) и т.д.).
![Recursion tree for permutations of string "ABC"]()
Источник: http://www.geeksforgeeks.org/write-a-c-program-to-print-all-permutations-of-a-given-string/
Ответ 4
Рекурсия действительно упрощает его:
public static void permutation(String str)
{
permutation("", str);
}
private static void permutation(String prefix, String str)
{
int n = str.length();
if (n == 0) {
System.out.println(prefix);
} else {
for (int i = 0; i < n; i++)
permutation(prefix + str.charAt(i), str.substring(0, i) + str.substring(i+1, n));
}
}
Ответ 5
Псевдокод:
String permute(String a[])
{
if (a[].length == 1)
return a[];
for (i = 0, i < a[].length(); i++)
append(a[i], permute(a[].remove(i)));
}
Ответ 6
I create more specific but not efficient Program for permutation for general string.
It work nice way.
//ubuntu 13.10 and g++ compiler but it works on any platform and OS
//All Permutation of general string.
#include<iostream>
#include<stdio.h>
#include<string>
#include<string.h>
using namespace std;
int len;
string str;
void permutation(int cnum)
{
int mid;
int flag=1;
int giga=0;
int dead=0;
int array[50];
for(int i=0;i<len-1;i++)
{
array[50]='\0';
dead=0;
for(int j=cnum;j<len+cnum;j++)
{
mid=j%len;
if(mid==cnum && flag==1)
{
cout<<str[mid];
array[dead]=mid;
dead++;
flag=0;
}
else
{
giga=(i+j)%len;
for(int k=0;k<dead;k++)
{
if((array[k]==giga) && flag==0)
{
giga=(giga+1)%len;
}
}
cout<<str[giga];
array[dead]=giga;
dead++;
}
}
cout<<endl;
flag=1;
}
}
int main()
{
cout<<"Enter the string :: ";
getline(cin,str);
len=str.length();
cout<<"String length = "<<len<<endl;
cout<<"Total permutation = "<<len*(len-1)<<endl;
for(int j=0;j<len;j++)
{
permutation(j);
}
return 0;
}
Ответ 7
# include <stdio.h>
/* Function to swap values at two pointers */
void swap (char *x, char *y)
{
char temp;
temp = *x;
*x = *y;
*y = temp;
}
/* Function to print permutations of string
This function takes three parameters:
1. String
2. Starting index of the string
3. Ending index of the 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++)
{
swap((a+i), (a+j));
permute(a, i+1, n);
swap((a+i), (a+j)); //backtrack
}
}
}
/* Driver program to test above functions */
int main()
{
char a[] = "ABC";
permute(a, 0, 2);
getchar();
return 0;
}
Ответ 8
Я столкнулся с той же проблемой, анализируя выполнение этого алгоритма возврата в GeeksForGeeks. Посмотрите сами, как это выполняется. Иногда значения печати действительно помогают визуализировать выполнение программы
swap((a+l), (a+i)); ~~~~ Forward swap the //////// i= 0 //////// l = 0 //////// r = 2 //////// string = ABC
permute(a, l+1, r); ==== Values send to permute i.e. string= ABC //////// (l+1) = 1 //////// r = 2
swap((a+l), (a+i)); ~~~~ Forward swap the //////// i= 1 //////// l = 1 //////// r = 2 //////// string = ABC
permute(a, l+1, r); ==== Values send to permute i.e. string= ABC //////// (l+1) = 2 //////// r = 2
ABC
______________________________________________________________________
swap((a+l), (a+i));++++ Backtract swap //////// i= 1 //////// l = 1 //////// r = 2 //////// string = ABC
---------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------
------------------------------END OF BACKTRACK--------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------
swap((a+l), (a+i)); ~~~~ Forward swap the //////// i= 2 //////// l = 1 //////// r = 2 //////// string = ACB
permute(a, l+1, r); ==== Values send to permute i.e. string= ACB //////// (l+1) = 2 //////// r = 2
ACB
______________________________________________________________________
swap((a+l), (a+i));++++ Backtract swap //////// i= 2 //////// l = 1 //////// r = 2 //////// string = ABC
---------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------
------------------------------END OF BACKTRACK--------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------
swap((a+l), (a+i));++++ Backtract swap //////// i= 0 //////// l = 0 //////// r = 2 //////// string = ABC
---------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------
------------------------------END OF BACKTRACK--------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------
swap((a+l), (a+i)); ~~~~ Forward swap the //////// i= 1 //////// l = 0 //////// r = 2 //////// string = BAC
permute(a, l+1, r); ==== Values send to permute i.e. string= BAC //////// (l+1) = 1 //////// r = 2
swap((a+l), (a+i)); ~~~~ Forward swap the //////// i= 1 //////// l = 1 //////// r = 2 //////// string = BAC
permute(a, l+1, r); ==== Values send to permute i.e. string= BAC //////// (l+1) = 2 //////// r = 2
BAC
______________________________________________________________________
swap((a+l), (a+i));++++ Backtract swap //////// i= 1 //////// l = 1 //////// r = 2 //////// string = BAC
---------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------
------------------------------END OF BACKTRACK--------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------
swap((a+l), (a+i)); ~~~~ Forward swap the //////// i= 2 //////// l = 1 //////// r = 2 //////// string = BCA
permute(a, l+1, r); ==== Values send to permute i.e. string= BCA //////// (l+1) = 2 //////// r = 2
BCA
______________________________________________________________________
swap((a+l), (a+i));++++ Backtract swap //////// i= 2 //////// l = 1 //////// r = 2 //////// string = BAC
---------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------
------------------------------END OF BACKTRACK--------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------
swap((a+l), (a+i));++++ Backtract swap //////// i= 1 //////// l = 0 //////// r = 2 //////// string = ABC
---------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------
------------------------------END OF BACKTRACK--------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------
swap((a+l), (a+i)); ~~~~ Forward swap the //////// i= 2 //////// l = 0 //////// r = 2 //////// string = CBA
permute(a, l+1, r); ==== Values send to permute i.e. string= CBA //////// (l+1) = 1 //////// r = 2
swap((a+l), (a+i)); ~~~~ Forward swap the //////// i= 1 //////// l = 1 //////// r = 2 //////// string = CBA
permute(a, l+1, r); ==== Values send to permute i.e. string= CBA //////// (l+1) = 2 //////// r = 2
CBA
______________________________________________________________________
swap((a+l), (a+i));++++ Backtract swap //////// i= 1 //////// l = 1 //////// r = 2 //////// string = CBA
---------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------
------------------------------END OF BACKTRACK--------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------
swap((a+l), (a+i)); ~~~~ Forward swap the //////// i= 2 //////// l = 1 //////// r = 2 //////// string = CAB
permute(a, l+1, r); ==== Values send to permute i.e. string= CAB //////// (l+1) = 2 //////// r = 2
CAB
______________________________________________________________________
swap((a+l), (a+i));++++ Backtract swap //////// i= 2 //////// l = 1 //////// r = 2 //////// string = CBA
---------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------
------------------------------END OF BACKTRACK--------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------
swap((a+l), (a+i));++++ Backtract swap //////// i= 2 //////// l = 0 //////// r = 2 //////// string = ABC
---------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------
------------------------------END OF BACKTRACK--------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------
Ответ 9
def perms(s):
if len(s) < 1:
return [s]
ps = []
for i in range(0, len(s)):
head, tail = s[i], s[0:i] + s[i + 1:]
ps.extend([head + tailp for tailp in perms(tail)])
return ps