Algorithm 函数生成元素限制为1个相邻移动的序列置换

Algorithm 函数生成元素限制为1个相邻移动的序列置换,algorithm,sequence,Algorithm,Sequence,假设有一个长度为n的列表,其中包含字母a-char(n)。我想找出每一个字母只能相邻移动或保持不变的排列方式。因此,对于每个序列,有三个“集合”排列,向左循环,向右循环(列表被认为是循环的),以及原始列表。我很难想出一个算法来处理列表中间的可能掉期。主要是,要交换的字母配对方式可以跳过字母。 例如:n=3的列表的排列[ABC、CAB、BCA、ACB、CBA、BAC] 此外,ABC和CAB被认为是唯一的,尽管元件彼此具有相同的位置。主要是寻找算法,而不是任何特定的语言。 基本规则是,元素在列表中的

假设有一个长度为n的列表,其中包含字母a-char(n)。我想找出每一个字母只能相邻移动或保持不变的排列方式。因此,对于每个序列,有三个“集合”排列,向左循环,向右循环(列表被认为是循环的),以及原始列表。我很难想出一个算法来处理列表中间的可能掉期。主要是,要交换的字母配对方式可以跳过字母。 例如:n=3的列表的排列[ABC、CAB、BCA、ACB、CBA、BAC] 此外,ABC和CAB被认为是唯一的,尽管元件彼此具有相同的位置。主要是寻找算法,而不是任何特定的语言。 基本规则是,元素在列表中的原始位置最多可以偏离1个位置

OK新方法:

function(String begin,String end)
  • 如果结束大小==1:打印开始+结束
  • 循环结束:
  • ch=结束[i]
  • newString=从末尾删除索引i
  • 函数(begin+ch,newString)

  • 我将草拟一个有效的枚举策略

    首先,让我们解决一个更简单的问题,其中没有概括。最左边的元素有两种可能。要么保持不动,要么向右移动。如果它向右移动,则它所置换的图元必须向左移动。我们可以递归地枚举置换其余部分的可能性

    # this code is for the simpler problem, without wraparound
    # the algorithm for the problem with wraparound is described in prose below
    
    def perms_line(lst, j):
        if len(lst) - j < 2:
            print(lst)
        else:
            perms_line(lst, j + 1)
            lst[j], lst[j + 1] = lst[j + 1], lst[j]
            perms_line(lst, j + 2)
            lst[j], lst[j + 1] = lst[j + 1], lst[j]
    
    perms_line([1, 2, 3, 4, 5], 0)
    
    #此代码用于更简单的问题,无需概括
    #下面以散文的形式描述了这个问题的算法
    def perms_管线(lst,j):
    如果len(lst)-j<2:
    打印(lst)
    其他:
    永久线(lst,j+1)
    lst[j],lst[j+1]=lst[j+1],lst[j]
    永久线(lst,j+2)
    lst[j],lst[j+1]=lst[j+1],lst[j]
    perms_线([1,2,3,4,5],0)
    
    现在让我们来考虑一下。如果两个连续的元素向右移动,则每个元素都必须向右移动。如果两个连续的元素向左移动,则每个元素都必须向左移动。分别处理这些异常排列


    开始时,考虑最左边的元素。它要么保持不变,要么与其右侧的元素交换,要么与最右侧的元素交换。对于这三种可能性中的每一种(注意:如果n=2,则为两种,如果n=1,则仅为一种),对置换的其余部分使用无环绕枚举策略。我将继续编写代码,因为这需要一些修改才能正确。

    如果我正确理解您的问题,您需要找到循环序列的所有排列,这些排列可以通过选择一组不重叠的相邻对并交换每对中的两个元素来生成

    相邻对可由该对中的第一元素唯一地识别;如果一组相邻的对不包括两个连续的元素,则它是不重叠的。没有循环性方面,这只是斐波那契编码:非相邻元素集(NA)可以递归生成,如下所示:

    NA({a1,a2,…,an}, T) = NA({a2,a3,…,an}, T) ⋃ NA({a3,a4,…,an}, T ⋃ {a1}) NA({a}, T) = { T ⋃ {a} } NA({}, T) = { T }
    由于这是根据
    NA
    定义的,我们可以看到
    CNA
    的集合计数是
    fibonacci(n)+fibonacci(n-2)

    你能给出一个无效排列的例子吗,可能从
    n=4
    ?无效的置换可能是CBAD,因为C无法到达位置1,因为它只能向左或向右移动1个位置。允许多少相邻的交换构造一个置换?交换总数没有限制,但每个元素每次置换只能移动一次。对于n=6,创建一个置换的最大交换数为3(3对可以交换),最小交换数为1(不包括原始列表)。我们如何从
    ABC
    移动到
    BCA
    ?你是说元素现在离其在“原始”/“有序”排列中的位置最多一步的任何排列都是有效的吗?或者,您的意思是,可以通过每个元素最多一次相邻交换来实现的任何置换都是有效的吗?您所说的下一个可用字母是什么意思?例如,循环/递归第一次运行时,输出不是“a”xn吗?(“aaa”如果n=3)好的,那么让我们假设n=3。第一次运行的列表是ABC,在第一次递归调用之后,列表应该是AB还是BC?或者别的什么?应该是我的错。我的alg。是有缺陷的,但如果您注意到了这一点,那么修复它应该是相当容易的。我很快就要编辑了。所以我对它做了一点修改。在原始序列中发送,然后在调用dofunction(list[1:],n-1)中的递归函数时,它只是删除了列表的第一个字母,我认为这是您试图做的(可能是错误的)。但从那里,我得到的输出像[ABC,CC,BBC,CC,CBC,CC],我猜是因为换行语句的位置,但我不确定。如果您愿意,我可以发布我的代码,但我认为这可能是一个算法问题。这次,OK使用了不同的方法。试试看。[2,3,4,5,1]也是有效的(参见原始问题下的注释)。@1490㪞עדברקן这是一种例外排列。哦,对不起,我刚刚尝试了你的代码,但没有列出它。这个解决方案对我有效。为了进行概括,我只需在调用函数之前切换第一个和最后一个元素。J设置为1,因此第一个元素不交换,len(lst)-J<3,因此最后一个元素不交换。谢谢 CNA({a1,a2,…,an}) = NA({a2,a3,…,an}, {}) ⋃ NA({a3,a4,…,an-1}, {a1})