回家了很少看了,今天突然心血来潮做了今天的每日一题,还不错,最后是一次AC,说明这么长时间没看实力没有下降多少,哈哈哈哈,自恋一下,后面我会更新一些课设和实验作业,进入正题。
给你一个偶数 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
1000=>n>=2
这道题第一眼反应是dp,因为做了很多dp的题目所以第一反应就是dp,认真看一下发现应该是数学规律,因为题目给的条件很容易让人想到是摸索规律,发现给n赋予一些值之后比如4.6.8进行测试发现就是每次把下标为偶数的数组值提前,为奇数的往后放,依据这个规律我们只需要找一个代表的偶数和代表的奇数,当他们两同时归位的时候我们就认为整体是归位好的,这个证法是正确的,所以我们只需要将题目给的条件封装成一个函数即可求解
int f(int x,int n)
{
if(x%2==0)
{
return x/2;
}else{
return n/2+(x-1)/2;
}
}
int reinitializePermutation(int n){
if(n==2)
{
return 1;
}
int p=(n-1)/2,q=(n-1)/2+1,i,j,flag=1;
i=f(p,n);
j=f(q,n);
while(i!=p&&j!=q)
{
i=f(i,n);
j=f(j,n);
flag++;
}
return flag;
}