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

题目链接

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

题目描述

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

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

如果 i i i 是偶数 ,那么 a r r [ i ] = p e r m [ i / 2 ] arr[i] = perm[i / 2] arr[i]=perm[i/2]
如果 i i i 是奇数 ,那么 a r r [ i ] = p e r m [ n / 2 + ( i − 1 ) / 2 ] arr[i] = perm[n / 2 + (i - 1) / 2] arr[i]=perm[n/2+(i1)/2]
然后将 a r r ​​ arr​​ arr​​ 赋值​​给 p e r m perm perm

要想使 p e r m 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 2 <= n <= 1000 2<=n<=1000
n​​​​​​ 是一个偶数

解法一:由于数据量比较小,我们可以直接进行模拟

  • 时间复杂度: O ( n 2 ) O(n^2) O(n2)

代码:

class Solution {
public:
    int reinitializePermutation(int n) {
        vector<int> prem(n),arr(n);
        for(int i = 0;i < n;i++) prem[i] = i;

        int ans  = 0;
        while(true){
            ans++;
            for(int i = 0;i < n;i++){
                if(i % 2) arr[i] = prem[n/2 + (i-1)/2];
                else arr[i] = prem[i/2];
            }
            prem = arr;
            bool ok = true;
            for(int i = 0;i < n;i++){
                if(prem[i] != i){
                    ok = false;
                    break;
                }
            }
            if(ok) break;
        }
        return ans;
    }
};

解法二:找规律

在这里插入图片描述

  • 时间复杂度: O ( n ) O(n) O(n)

C++代码:

class Solution {
public:
    int reinitializePermutation(int n) {
        int ans = 0;
        int i = 1;
        while(true){
            ans++;
            if(i < n / 2) i <<= 1;
            else i = (i - n/2) << 1 | 1;
            if(i == 1) break;
        }
        return ans;
    }
};

Java代码:

class Solution {
    public int reinitializePermutation(int n) {
        int ans = 0;
        int i = 1;
        while(true){
            ans++;
            if(i < n / 2) i <<= 1;
            else i = (i - n/2) << 1 | 1;
            if(i == 1) break;
        }
        return ans;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值