Leetcode 1806. 还原排列的最少操作步数

一、题目内容和对应链接

1.题目对应链接

Leetcode 1806. 还原排列的最少操作步数

2.题目内容

给你一个偶数 n​​​​​​ ,已知存在一个长度为 n 的排列 perm ,其中 perm[i] == i​(下标 从 0 开始 计数)。

一步操作中,你将创建一个新数组 arr ,对于每个 i :

  • 如果 i % 2 == 0 ,那么 arr[i] = perm[i / 2]
  • 如果 i % 2 == 1 ,那么 arr[i] = perm[n / 2 + (i - 1) / 2]
    然后将 arr​​ 赋值​​给 perm 。

要想使 perm 回到排列初始值,至少需要执行多少步操作?返回最小的 非零 操作步数。

示例 1:

输入:n = 2
输出:1
解释:最初,perm = [0,1]
第 1 步操作后,perm = [0,1]
所以,仅需执行 1 步操作

示例 2:

输入:n = 4
输出:2
解释:最初,perm = [0,1,2,3]
第 1 步操作后,perm = [0,2,1,3]
第 2 步操作后,perm = [0,1,2,3]
所以,仅需执行 2 步操作

示例 3:

输入:n = 6
输出:4

提示:

  • 2 <= n <= 1000
  • n​​​​​​ 是一个偶数

二、我的想法

  1. 最开始观察了下,发现给的示例里面,第一步操作之后,和原数组不同的值的数量就是返回值,于是按着这个写了。
class Solution:
    def reinitializePermutation(self, n: int) -> int:
        perm = [i for i in range(n)]
        arr = [i for i in range(n)]
        returnnum = 0
        for i in range(n):
            if i % 2 == 0:
                arr[i] = perm[int(i//2)]
            elif i % 2 == 1:
                arr[i] = perm[int(n // 2 + (i - 1) // 2)]
            print(arr[i], i)
            if arr[i] != i:
                returnnum += 1
        if returnnum == 0 :
            return 1
        else:
            return returnnum
  1. 然后没过,我手动写了下 n = 10 时的数组。
    【0 1 2 3 4 5 6 7 8 9】
    【0 5 1 6 2 7 3 8 4 9】

n =10 的时候返回值为 6。
我想到,

如果 i % 2 == 0 ,那么 arr[i] = perm[i / 2]
如果 i % 2 == 1 ,那么 arr[i] = perm[n / 2 + (i - 1) / 2]

这个其实是固定的,对应的 arr[i] 值一定有一个固定的 perm[]值。

我想了下可能是要从 1 开始手尾相连的个数?
1 - 5,5 - 7,7 - 8,8 - 4, 4 - 2, 2 - 1
而 3 - 6, 6 - 3 每两次循环就换过来了,0 - 0 和 9 - 9永远不变。

那可以经历一次循环取到键值对,然后最后来一个循环看键值对需要经历多少步骤能够得到手尾相连。

class Solution:
    def reinitializePermutation(self, n: int) -> int:
        if n == 2 :
            return 1
            
        perm = [i for i in range(n)]
        arr = [i for i in range(n)]
        newdict = defaultdict(int)
        returnnum = 0
        for i in range(n):
            if i % 2 == 0:
                arr[i] = perm[int(i//2)]
            elif i % 2 == 1:
                arr[i] = perm[int(n // 2 + (i - 1) // 2)]
            newdict[i] = arr[i] # 取到键值对
            
        i = 1
        left = 1
        while i <= len(newdict):
            if newdict[i] != i and newdict[i] != left:
                i = newdict[i]
                returnnum += 1
            if newdict[i] == left:
                returnnum += 1
                return returnnum

三、其他人的题解

官方 - 模拟 / 数学,数学解法得这个欧拉定理我是一点也不会。
Tizzi - 模拟 / 模拟优化 ,我很喜欢这个模拟优化的想法。
ylb - 找规律 + 模拟,说明了为什么要从1开始算。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值