为了账号安全,请及时绑定邮箱和手机立即绑定

全排列及相关扩展算法(四)——原始中介数通过逆推求原排列算法

标签:
C++

1.中介数逆推原排列:上一章我们讲到了中介数,通过一个排列可以很方便地求数它的中介数,通过中介数也可以很方便地求出排位序号。但是通过中介数逆推原排列就不是那么容易了。因为我们每求一位数,都需要对比其前面所有的数来获取他的定位,以上一章{ 3,4,5,6,7,2,1 }为例,得到的{2,2,2,2,2,1}中介数,第一位我们可以直接得出3,第二位本应也是3,但是考虑前面已经有3了,所以第二位就只能是4,以此类推……即:如果之前存在某排位i小于等于当前排位,那么当前排位所对应的数需要再加上1

2.原中介数逆推求原排列代码(错误版):

int* get_permutation(int medium[], int n)
{
int* temp = new int[n + 1];
for (int i = 0; i <= n; i++)
{
temp[i] = i == n ? 1 : medium[i] + 1;
}
 
for (int i = 0; i <= n ; i++)
{
for (int j = i - 1; j >= 0; j--)
{
if ((medium[j] <= (i == n ? 1 : medium[i]))||(temp[j] <= temp[i]))
{
temp[i]++;
}
}
}
return temp;
}

解释一下这种思路:以{ 7,6,8,3,4,5,1,2 }为例,其中序数为{6,5,5,2,2,2,0}


①第一位是7

②第二位是6

③第三位原本应为6,但是其与第二位中序数相等(medium[j] <= (i == n ? 1 : medium[i]),故加1。加完1后第三位原本应为7,但又与第一位的7真实数相等(temp[j] <= temp[i]),故第三位为8

④第四位为3

⑤第五位为3,但因为与第四位中序数相等(medium[j] <= (i == n ? 1 : medium[i]),故为4

⑥第六位为3,且此时小于第五位的真实数(4),但是其原本的中序数等于第五位,故其为+1为4,再与第四位对比,变成5

⑦第七位为1,

⑧第八位为1,但与第七位相等,故为2


也就是说,我们定位当前位i不但要考虑其原始中序数值(medium[j] <= (i == n ? 1 : medium[i])的关系,还要经过逆推考虑影响后,其真实数值的关系(temp[j] <= temp[i])

看似没有什么问题,我们再看一组测试样例:{ 3,6,4,7,5,2,1 },其中中序数为{2,4,2,3,2,1}

①第一位是3

②第二位原本应是5,但大于第一位,故是6

③第三位原本应是3,但大于第一位,故是4

④第四位原本应是4,但等于第三位,故是5,然后小于第二位,继续向前,大于第一位,故为6

注意!!第四位竟然是6,但实际上此时已经与第二位冲突了。

https://img1.sycdn.imooc.com//5b3e2f2c0001f4dc07950237.jpg

这里我们发现了,我们无法确定后续的比较当前点i能走到什么值,所以当我们判断某一个点j的时候是无法确定j点真实值是否小于i点的。比较简单的解决方式是保证遍历的时候是从小到大进行比对,这样我们就要将在此之前确定好真实值的数组进行递减排序。

代码如下:

int* get_permutation(int medium[], int n)
{
int* temp = new int[n + 1];
int* permutation = new int[n + 1];
for (int i = 0; i <= n; i++)
{
permutation[i]=temp[i] = i == n ? 1 : medium[i] + 1;
}
 
for (int i = 0; i <= n ; i++)
{
for (int j = i - 1; j >= 0; j--)
{
if (temp[j] <= temp[i])
{
temp[i]++;
permutation[i]++;
}
else
{
break;
}
}
sort(temp,temp + i+1, greater<int>());
}
return permutation;
}

https://img1.sycdn.imooc.com//5b3e2f6f000127e507370232.jpg

所以看出,这种中介数求原排列实际上非常的复杂。

外部调用:

int main()
{
int A[] = { 7,6,8,3,4,5,1,2 };
 
int n = sizeof(A) / sizeof(A[0]);
int *medium = get_permutation_medium(A, n);
Print(medium, n-1);
//中序数长度比原排列小1
int *B = get_permutation(medium, n - 1);
Print(B,n);
//int rank =get_permutation_rank(medium, n);
//printf("%d\n",rank);
system("pause");
return 0;
}

3.运行截图:

https://img1.sycdn.imooc.com//5b3e2fab0001fe8f08530426.jpg

https://img1.sycdn.imooc.com//5b3e2fba0001463f08150439.jpg

4.参考文档

https://wenku.baidu.com/view/8c79a2facc17552706220880.html


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消