计算变化数组中的预期反转次数[关闭]

Posted

技术标签:

【中文标题】计算变化数组中的预期反转次数[关闭]【英文标题】:Calculation of Expected number of inversions in a changing array [closed] 【发布时间】:2014-09-09 17:42:28 【问题描述】:

问题:我们有一个大小为n的数组,我们最多可以执行K操作,每个操作都可以

    将反转次数减少 1。 对整个数组进行随机洗牌。

我的问题是执行K 操作,以使最终数组中的预期反转次数最小化。

约束: 100 个带有 的测试用例 1 1

我的方法:我正在考虑动态编程解决方案。我可以使用马洪数计算在大小为n 的数组中恰好有e 反转的概率。我还按行填充数组dp[k+1][1+n(n-1)/2],这样dp[i][j] 表示在执行i 操作之后具有j 反转的数组中的最小预期反转然后使用它我可以生成@987654331 的最小预期值数组中所有可能的反转的@操作。

由于 c++ 中双精度数的限制,这种方法的问题是概率不准确,并且该算法对于每个测试用例都是 O(kn<sup>2</sup>),这非常慢。

例如: 在大小为 100 的数组中没有反转的概率 = 1.0/factorial(100) ~ 10<sup>-160</sup>(我认为这里缺乏精度)。

我认为有一些准确和更有效的方法。请提出一些想法。

谢谢

【问题讨论】:

对于操作 #2,您的意思是对连续子数组进行随机洗牌,即索引在 i 和 j 之间的所有元素的子数组,其中 1 @user2566092 是整个数组的随机洗牌 @userDD 实际上我认为如果数组很大并且操作次数很少我错了,那么最好保持随机改组数组,直到你得到足够低的反转次数机会,然后一旦你这样做了,你就可以通过将其余操作的反转次数减少 1 来完成。 @user2566092 在第一步中,我们可以将反转次数减少到 min(n(n-1)/4,currentInvCount - 1 ),但是在 k 次操作之后我们不能做任何事情。 @btilly 你是对的; this problem 来自 2014 年 9 月的同一场比赛。一旦这条评论在首屏可见,我将删除另一条评论。 【参考方案1】:

为了回答您的问题,您将需要能够计算预期的#inversions,假设您有 k 个左移并假设在第 k 个移动时您洗牌,然后您决定停止洗牌(然后只需减去1)或继续洗牌,具体取决于洗牌后获得的反转次数。如果您只剩下两步并且当前的#inversions 大于n(n-1)/4,这很容易。基本上你先洗牌,然后停止洗牌,如果在你第一次洗牌后反转次数为 n(n-1)/4 或更低,则停止洗牌并为你的第二步减去 1,如果反转次数大于 n,你再次洗牌(n-1)/4 在你第一次洗牌后。但是,对于超过 2 步,事情会变得更加复杂,因为在第 k 步时,如果您洗牌,您可以选择反转次数 Nk 的上限 Nk,然后您将停止并减去 1,并且您需要优化此 Nk因此预期的反转次数总体上是最小的。显然,如果 k 较大,则应选择较小的 Nk,但问题是多少。如果您可以计算 Nk(对于每个 k),那么您将解决您的问题。

我的直觉是,您可以使用某种递归公式在基本上 O(nK) 时间内求解所有 k=1,2,...,K 的 Nk。如果我弄清楚细节,我会更新。如果为真,则意味着您也可以在基本上 O(nK) 的时间内求解出预期的反演次数。

【讨论】:

以上是关于计算变化数组中的预期反转次数[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

分而治之算法(MergeSort Algo)计算反转次数

如何计算元素在数组中特定位置出现的次数? [关闭]

Vue计算属性未按预期工作[关闭]

访问:计算 2 列中的出现次数 [关闭]

检测数组中的符号变化[关闭]

如何在 C++ 中反转字符数组? [关闭]