【问题标题】:Program to print permutations of given elements [closed]打印给定元素排列的程序[关闭]
【发布时间】:2012-02-05 10:34:21
【问题描述】:

我最近参加了 ACM 认证编程竞赛。这是我当时做不到的问题:

“给定一个包含 n 个元素的整数数组,编写一个程序来打印所有排列。”

请告诉我如何回答这个问题。有什么算法可以做这类题吗?

【问题讨论】:

  • 我尝试通过更改元素的顺序以不同的排列方式打印数组的元素,但这不起作用,并且它不会打印 n 个阶乘顺序。
  • 是否有重复? [1,2,3,1] 是有效输入吗?如果是 - 简单的“打印所有可能性”将不起作用,因为您需要“记住”已经打印了哪些排列
  • 题目没有时间限制,但程序越快,获得的分数越多。
  • 这个问题没有说明任何关于重复的信息。但如果把重复去掉就更好了。
  • 本站给出了很好的迭代解释:nayuki.io/page/next-lexicographical-permutation-algorithm

标签: c algorithm


【解决方案1】:

假设没有重复:只需用所有可能的后续元素更改每个元素,然后递归调用函数。

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 处的元素与随机选择的以下元素交换 - 你将其与所有元素交换 -一次一个。

【讨论】:

  • 为什么末尾有return;
【解决方案2】:

递归方法应该没问题:

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

【讨论】:

    【解决方案3】:

    这是一个迭代解决方案:

    首先对数组进行排序。

    • 找到最大索引 i a[i+1]。 (如果不存在这样的索引,则没有更多的排列)

    找到最大索引 j

    交换 a[i] 和 a[j]。

    反转a[i+1]..a[n-1]并转到步骤*。

    【讨论】:

    • 这是唯一真正有用的答案。它无助于作弊,但仍然提供信息。
    【解决方案4】:

    为了得到你必须使用回溯和回溯的排列,你也可以通过蛮力解决它,但它变得复杂

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-05-10
      • 2020-08-22
      • 1970-01-01
      • 2014-07-11
      • 2015-01-04
      • 2016-02-18
      相关资源
      最近更新 更多