置换群Larry‘s Array

HackerRank Larry’s Array两种解法

这道题目并不出名,但更巧妙的的思路涉及数学中的置换群。有必要留意一下这方面的理论。

下面是Larray’s Array问题

Problem
这道题目需要通过3个数字的若干次轮换操作将原始序列变为有序,
问是否存在这样的操作集合或者序列。

解法一: 冒泡轮换法

容易观察原始序列一定可以将最后2个最大数字之外的数字置换至最终有序数组位置,所以第一种思路是遍历数组,从最小到倒数第三个依次向左移动(置换),最后判断剩余2个数的顺序即可,代码如下。

def sortMin(arr, i):
    mid = arr[i:].index(min(arr[i:])) + i
    while i != mid:
        s = max(mid-2,i) # mid-2 is the 1th, prev 2
        a = arr[s:s+3]
        a = a[a.index(min(a)):] + a[:a.index(min(a))]
        arr[s:s+3] = a
        mid = s # arr[i] != s[0] 则继续冒泡
    
def larrysArray(A):
    # Write your code here
    for i in range(0, len(A)-2):
        sortMin(A, i)
    return 'YES' if A[-2] > A[-3] and A[-1] > A[-2] else 'NO'

测试结果全部AC, 该解法每步迭代轮换均使得最小值([min(mid-2, i), +2])居前, 分析可知该算法时间复杂度 O ( n 2 ) O(n^2) O(n2) 另外直观感觉轮换操作序列不唯一,需要探究置换的等价性,利用这种性质(置换奇偶性)判断是否存在合理操作序列.

解法二: 置换全排序为偶
置换群

这里需要引入群论中置换群的概念, 置换群不是某种带有置换属性的群,而是群的元素为置换。 对任意置换,可以找到若干互不重合的轮换组合。我们约定循环节表示法为顺序排列的置换 [ a 1 , a 2 , . . . a n ] ( 1 , 2 , 3.. n ) [a_1,a_2, ...a_n](1,2,3..n) [a1,a2,...an](1,2,3..n)( a n a_n an为位置n上的元素)即为单次轮换操作。如对于置换(2,1)可等价于(1,2)的单次轮换。 特别的, 如 π=(123)(3)(45)(6)(7) 表示拥有7个元素 [ a 1 , a 2 . . . a 7 ] [a_1, a_2...a_7] [a1,a2...a7]的集合或者列表中, [ a 1 , a 2 , a 3 ] [a_1,a_2,a_3] [a1,a2,a3]轮换, [ a 3 ] [a_3] [a3]不变, [ a 4 , a 5 ] [a_4,a_5] [a4,a5]轮换, [ a 6 , a 7 ] [a_6,a_7] [a6,a7]不变。

置换的运算逻辑:

例如对于排列或者列表[A,B,C,D], 取(1,2,3)轮换, 记作 [ A , B , C , D ] ( 1 , 2 , 3 ) = [ B , C , A , D ] [A,B,C,D](1,2,3) = [B,C,A,D] [A,B,C,D](1,2,3)=[B,C,A,D]
又如 [ A , B , C , D ] ( 1 , 2 , 3 ) ( 3 , 4 ) = [ B , C , A , D ] ( 3 , 4 ) = [ B , C , D , A ] [A,B,C,D](1,2,3)(3,4) = [B,C,A,D](3,4) = [B,C,D,A] [A,B,C,D](1,2,3)(3,4)=[B,C,A,D](3,4)=[B,C,D,A]
再比如,将正方形绕其中心逆时针旋转90度,可以看成是正方形四个顶点 [ A , B , C , D ] [A,B,C,D] [A,B,C,D]的一个轮换(置换)。

置换类型格式
空操作e
轮换/互换(1,2) (2,1) (1,2,3)
轮换组合(1,2)(2,1) = e

其中2元的置换为互换,互换是特殊的轮换, 轮换是特殊的置换,置换可以写成若干轮换的组合。由这些操作可知,置换操作满足封闭性和交换律,单位元以及逆元的操作都成立,故置换操作可以构成严格意义上的群概念。

置换奇偶性

置换的奇偶性可以简化为 反向对个数的奇偶性, 即满足x,y位置的元素 x < y , s g n ( x ) > s g n ( y ) x<y, sgn(x)>sgn(y) x<y,sgn(x)>sgn(y)

任意置换可以由一列对换产生:对第一个对换我们将置换的第一个元素放到它恰当的位置,第二个对换放第二个元素,等等。给定一个置换σ,我们可用无数种方式将其写成对换之积。我们要证明所有这样一个分解,要么都有偶数个对换,要么有奇数个对换。
置换等价性维基百科
对于一般置换, 都可以可以写成二元互换的复合, 如本题中
A,B,C->C,A,B: (1,2,3) = (1,3)(2,3) , 逆序对[C,A], [C,B]为2
A,B,C->B,C,A: (1,2,3) = (1,2)(2,3), 逆序对[B,A], [B,A]为2
对于偶置换,置换所指定的一个全排序可以保持不变。

总结过后就可以使用原始的对换序列进行置换分解,并且该置换操作为偶置换即可满足全排序条件,实现如下:

  def inversion():
	  inversions = 0
	  for i in range(n-1):
	       for j in range(i+1, n):
	          if arr[i] > arr[j]:
	              inversions += 1
	  return inversions%2 == 0
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值