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]