我最近参加了ACM认证的编程竞赛。这是我当时不能做的问题:
“给定一个包含n个元素的整数数组,编写一个程序来打印所有排列。”
请告诉我如何解决这个问题。有没有算法来做这类问题?
答案 0 :(得分:27)
假设没有重复:只需用所有可能的后续元素更改每个元素,并递归调用该函数。
void permute(int *array,int i,int length) {
if (length == i){
printArray(array,length);
return;
}
int j = i;
for (j = i; j < length; j++) {
swap(array+i,array+j);
permute(array,i+1,length);
swap(array+i,array+j);
}
return;
}
您可以在ideone
的基本测试用例中看到辅助功能swap()
和printArray()
执行的代码
奖金:这类似于fisher-yates shuffle的想法,但是在这里 - 想要交换i
的元素和随机选择的后续元素 - 你用它交换它所有这些 - 每次都是。
答案 1 :(得分:12)
递归方法应该没问题:
If the list is empty
Return the only possible permutation, an empty list.
Else
For each element of the list
Put the element at the first place (i.e. swap it with the first element)
(If the element is same as the first one, don't swap)
Recursively find all the permutations of the rest of the list
此算法不会生成重复的排列。
这是一个python实现:
def permute(s):
if len(s) == 0:
return [[]]
ret = [s[0:1] + x for x in permute(s[1:])]
for i in range(1, len(s)):
if s[i] == s[0]:
continue
s[0], s[i] = s[i], s[0]
ret += [s[0:1] + x for x in permute(s[1:])]
return ret
s = [0, 1, 2, 3]
for x in permute(s):
print x
C中类似的事情应该是这样的:
void swap(char* str, int i, int j)
{
char temp = str[i];
str[i] = str[j];
str[j] = temp;
}
void permute(char *string, int start, int end)
{
if(start == end)
{
printf("%s\n", string);
return;
}
permute(string, start + 1, end);
int i;
for(i = start + 1; i < end; i++)
{
if(string[start] == string[i])
continue;
swap(string, start, i);
permute(string, start + 1, end);
swap(string, start, i);
}
}
答案 2 :(得分:2)
这是一个迭代解决方案:
首先对数组进行排序。
查找最大索引j
交换[i]和[j]。
反转[i + 1] .. a [n-1]并转到步骤*。
答案 3 :(得分:1)
要获得排列,你必须使用回击和回溯,你可以通过蛮力解决它但它变得复杂
void swap(int *x1,int *x2)
{
int x=*x1;
*x1=*x2;
*x2=x;
}
void per(int *arr,int st,int ls)
{
int i=0;
if(st==ls)
{
int k;
for(k=0;k<ls;k++)
{
printf("%d ",arr[k]);
}
printf("\n");
}
else
{
for(i=st;i<ls;i++)
{
swap(arr+st,arr+i);
per(arr,st+1,ls);
swap(arr+st,arr+i);
}
}
}
int main()
{
int arr[4]={1,2,3,1};
int st=0;
int ls=4;
per(arr,st,ls);
}