给定一个整数N,代表你有1~N这些数字。在给定一个整数K。你可以随意排列这些数字,但是每一种排列都有若干个逆序对。返回有多少种排列,正好有K个逆序对。

本文探讨了如何计算特定数量的逆序对排列数目问题,提供了两种动态规划方法的实现,并通过实例说明了算法的工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述:

        给定一个整数N,代表你有1~N这些数字。在给定一个整数K。你可以随意排列这些数字,但是每一种排列都有若干个逆序对。返回有多少种排列,正好有K个逆序对。

例子1:
        Input: n = 3, k = 0
        Output: 1
解释:
        只有[1,2,3]这一个排列有0个逆序对。

例子2:
        Input: n = 3, k = 1
        Output: 2
解释
        [3,2,1]有(3,2)、(3,1)、(2,1)三个逆序对,所以不达标。
        达标的只有:
        [1,3,2]只有(3,2)这一个逆序对,所以达标。
        [2,1,3]只有(2,1)这一个逆序对,所以达标。

代码

动态规划代码:

    public static int dp1(int N, int K) {
        if (N < 1 || K < 0) {
            return 0;
        }

        if (K == 0) {
            return 1;
        }
        int[][] dp = new int[N + 1][K + 1];
        dp[1][0] = 1;
        for (int i = 2; i <= N; i++) {
            dp[i][0] = 1;
        }
        for (int i = 2; i <= N; i++) {
            for (int j = 1; j <= K; j++) {
                for (int s = j; s >= Math.max(0, j - i + 1); s--) {
                    dp[i][j] += dp[i - 1][s];
                }
            }
        }
        return dp[N][K];
    }

优化动态规划中的迭代过程

    public static int dp2(int N, int K) {
        if (N < 1 || K < 0) {
            return 0;
        }
        if (K == 0) {
            return 1;
        }
        int[][] dp = new int[N + 1][K + 1];
        dp[1][0] = 1;
        for (int i = 2; i <= N; i++) {
            dp[i][0] = 1;
        }
        for (int i = 2; i <= N; i++) {
            for (int j = 1; j <= K; j++) {
//                if (i>j){
//                    dp[i][j] = dp[i][j-1]+dp[i-1][j];
//                }
//                if (i<=j){
//                    dp[i][j] = dp[i-1][j] + dp[i][j-1] -dp[i-1][j-1];
//                }
                dp[i][j] = dp[i][j - 1] + dp[i - 1][j] - (i <= j ? dp[i - 1][j - i] : 0);
            }
        }
        return dp[N][K];
    }

    public static void main(String[] args) {
        int N = 9;
        int K = 15;
        System.out.println(dp1(N, K));
        System.out.println(dp2(N, K));
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值