zoukankan      html  css  js  c++  java
  • LeetCode 629 K个逆序对数组

    题目链接:https://leetcode-cn.com/problems/k-inverse-pairs-array/

    题目大意

      略。

    分析

      首先,1~n 这 n 个数所能产生的最大逆序对为 n * (n - 1) / 2 对。
      设 dp[i][j] 表示 1~i 能产生 j 对逆序对的排列种数。
      这里定义一下如果下标为负数,这一项为 0
      在考虑接下来一个事实:对于序列 1,2,3,4,5 和 2,5,7,9,10,在这个问题下,我可以说这两个序列是等价的,因为产生逆序对的本质是大小关系而不是数实际的大小。
      现在考虑状态转移方程。
      首先当 j > i * (i - 1) / 2 时,dp[i][j] = 0。
      其次当 j = 0 时,dp[i][0] = 1,只有顺着排一种方法。
      以上确定了初始状态。
      对于其他 dp[i][j],我们如果考虑在队头放第 k 大的数,那么这个数就贡献了 k - 1 对逆序对,剩下的 i - 1 个不同的数就可以转化为子问题,也就是 dp[i - 1][j - k]。
      同理我们也可以在队头放其他数,分别求一下贡献,就能得到状态转移方程:$$dp[i][j] = sum_{k = max(0, j - i + 1)}^{j} dp[i - 1][k]$$
      仔细观察前后两项的关系可以发现:$$dp[i][j] = dp[i][j - 1] + dp[i - 1][j] - dp[i - 1][max(0, j - i + 1) - 1]$$
      不过不推这个式子也能做,搞个前缀和即可。

    代码如下

     1 class Solution {
     2     int dp[2][1007], mod = 1e9 + 7, now = 0;
     3 public:
     4     int kInversePairs(int n, int k) {
     5         dp[now][0] = 1;
     6         
     7         for(int i = 1; i <= n; ++i) {
     8             now = !now;
     9             dp[now][0] = 1;
    10             for(int j = 1; j <= k; ++j) {
    11                 if(2 * j > i * (i - 1)) break;
    12                 dp[now][j] = (dp[now][j - 1] + dp[!now][j]) % mod;
    13                 if(j - i >= 0) dp[now][j] = (dp[now][j] - dp[!now][j - i] + mod) % mod;
    14             }
    15         }
    16         
    17         return dp[now][k];
    18     }
    19 };
    View Code
  • 相关阅读:
    Erlang 杂记 IV
    ASP.NET MVC的View是如何被呈现出来的?[设计篇]
    面向对象—在线文件管理模块
    软件开发中个人在团队里的效绩评定
    用go语言遍历文件夹
    磁盘缓存的算法:写算法
    一种Lua到C的封装
    从信息系统界面设计引发的思考
    基于Backbone.js的JavaScript MVC示例程序
    C和C++
  • 原文地址:https://www.cnblogs.com/zaq19970105/p/11183886.html
Copyright © 2011-2022 走看看