LeetCode1806:还原排列的最少操作步数(置换群 or 模拟)

 

 题意:题目的意思是,给定一个初始状态perm,然后对perm的每个元素按照上述的规则进行变换操作。问:perm经过多少次这种操作能够变回初始的perm。

解题思路:第一种方法就是模拟,一直变换,直到变成原来的样子。

第二种解法:置换群与不相交循环,如图

 

 code:

#解法1:
class Solution(object):
    def check(self,n):
        for i in range(n):
            if self.perm[i]==self.arr[i]:
                continue
            else:
                return False
        return True

    def reinitializePermutation(self, n):
        self.perm = []
        for i in range(n):
            self.perm.append(i)
        step = 0
        self.arr = [0]*n
        tmp = self.perm[:]
        while self.check(n) is False:
            step+=1
            for i in range(n):
                if i %2 ==1:
                    self.arr[i] = tmp[n // 2 + (i - 1) // 2]
                else:
                    self.arr[i] =tmp[i//2]
            tmp = self.arr[:]
        return step
#
#解法2:
class Solution(object):
    def dfs(self,i,n):
        if self.vis[i] ==1:
            return 0
        else:
            self.vis[i]=1
            return 1+self.dfs(self.arr[i],n)
    def gcd(self,a,b):
        if a%b== 0:
            return b
        else:
            return self.gcd(b,a%b)
    def reinitializePermutation(self, n):
        self.perm = []
        for i in range(n):
            self.perm.append(i)
        self.arr= []
        for i in range(n):
            if i %2 ==1:
                self.arr.append( self.perm[n // 2 + (i - 1) // 2])
            else:
                self.arr.append( self.perm[i//2])
        self.vis= [0]*n
        ks = [1]
        for i in range(n):
            if self.arr[i]!=self.perm[i] and self.vis[i]==0:
                x = self.dfs(i,n)
                ks.append(x)
        while len(ks)>1:
            a=ks.pop()
            b = ks.pop()
            lcm = a*b//self.gcd(a,b)
            ks.append(lcm)
        return ks[0]

 

posted @ 2021-03-28 16:09  ISGuXing  阅读(196)  评论(0编辑  收藏  举报