zoukankan      html  css  js  c++  java
  • 629. K Inverse Pairs Array

    Given two integers n and k, find how many different arrays consist of numbers from 1 to n such that there are exactly k inverse pairs.

    We define an inverse pair as following: For ith and jth element in the array, if i < j and a[i] > a[j] then it's an inverse pair; Otherwise, it's not.

    Since the answer may be very large, the answer should be modulo 109 + 7.

    Example 1:

    Input: n = 3, k = 0
    Output: 1
    Explanation: 
    Only the array [1,2,3] which consists of numbers from 1 to 3 has exactly 0 inverse pair.
    

    Example 2:

    Input: n = 3, k = 1
    Output: 2
    Explanation: 
    The array [1,3,2] and [2,1,3] have exactly 1 inverse pair.
    

    Note:

    1. The integer n is in the range [1, 1000] and k is in the range [0, 1000].

    Approach #1: DP. [C++]

    class Solution {
    public:
        int kInversePairs(int n, int k) {
            vector<vector<int>> dp(n+1, vector<int>(k+1, 0));
            dp[0][0] = 1;
            for (int i = 1; i <= n; ++i) {
                for (int j = 0; j < i; ++j) {
                    for (int m = 0; m <= k; ++m) {
                        if (m - j >= 0 && m - j <= k) {
                            dp[i][m] = (dp[i][m] + dp[i-1][m-j]) % mod;
                        }
                    }
                }
            }
            return dp[n][k];
        }
        
    private:
        const int mod = pow(10, 9) + 7;
    };
    

      

    Analysis:

    For example, if we have some permutation of 1 ..... 4

    5 * * * * creates 4 new inverse pairs

    * 5 * * * creates 3 new inverse pairs

    * * 5 * * creates 2 new inverse pairs

    * * * 5 * creates 1 new inverse pairs

    * * * * 5 creates 0 new inverse pairs

    We can use this formula to solve this problem

    dp[i][j] : represent the number of permutations of (1 ... n) with k inverse pairs.

    dp[i][j] = dp[i-1][j] + dp[i-1][j-1] + dp[i-1][j-2] + ..... + dp[i-1][j-i+1]

    Approach #2 Optimization. [Java]

    class Solution {
        public int kInversePairs(int n, int k) {
            int mod = 1000000007;
            if (k > n*(n-1)/2 || k < 0) return 0;
            if (k == 0 || k == n*(n-1)/2) return 1;
            long[][] dp = new long[n+1][k+1];
            dp[2][0] = 1;
            dp[2][1] = 1;
            for (int i = 3; i <= n; i++) {
                dp[i][0] = 1;
                for (int j = 1; j <= Math.min(k, i*(i-1)/2); j++) {
                    dp[i][j] = dp[i][j-1] + dp[i-1][j];
                    if (j >= i) dp[i][j] -= dp[i-1][j-i];
                    dp[i][j] = (dp[i][j] + mod) % mod;
                }
            }
            return (int)dp[n][k];
        }
    }
    

      

    Analysis:

    Look back to the above formula.

    dp[i][j] = dp[i-1][j] + dp[i-1][j-1] + dp[i-1][j-2] + ..... +dp[i-1][j - i + 1]

    Let's consider this example

    if i = 5:

    dp[i][0] = dp[i-1][0] (creates 0 inverse pair)
    dp[i][1] = dp[i-1][0] (1) + dp[i-1][1] (0) = dp[i][0] + dp[i-1][1]
    dp[i][2] = dp[i-1][0] (2) + dp[i-1][1] (1) + dp[i-1][2] (0) = dp[i][1] + dp[i-1][2]
    .
    .
    .
    dp[i][4] = dp[i-1][0] (4) + dp[i-1][1] (3) + dp[i-1][2] (2) + dp[i-1][3] (1) + dp[i-1][4] (0) = dp[i][3] + dp[i-1][4]

    We can find the rules about above formula.

    if j < i, we can compute dp[i][j] = dp[i][j-1] + dp[i-1][j]

    So how about j >= i

    We know if we add number i into permutation(0 .. i-1), i can create 0 ~ i-1 inverse pair.

    If j >= i, we still use dp[i][j] = dp[i][j-1] + dp[i-1][j].

    We must minus dp[i][j-1]. (In fact it minus dp[i-1][j-1], because every j >= i in dp array, it minus dp[i-1][j-i] individually)

    For example, if i = 5

    dp[i][5] = dp[i][4] + dp[i-1][5] - dp[i-1][0]
    dp[i][6] = dp[i][5] + dp[i-1][6] - dp[i-1][1]

    Reference:

    https://leetcode.com/problems/k-inverse-pairs-array/discuss/104815/Java-DP-O(nk)-solution

    https://leetcode.com/problems/k-inverse-pairs-array/discuss/104825/Shared-my-C%2B%2B-O(n-*-k)-solution-with-explanation

    永远渴望,大智若愚(stay hungry, stay foolish)
  • 相关阅读:
    combobox下拉框只能选择不能编辑
    nginx 虚拟主机
    nginx加密网站
    nginx平滑升级
    http网站加密
    CentOS下网卡启动、配置等ifcfg-eth0教程
    CentOS5.6系统中安装并使用USB无线网卡(配置成功) 转
    【RedHat/Centos】利用iso镜像做本地yum源 转
    centOS6.0 64 位将光盘作为yum源(转)
    Linux安装无线网卡驱动,实现Linux无线上网 转
  • 原文地址:https://www.cnblogs.com/h-hkai/p/10506927.html
Copyright © 2011-2022 走看看