【LintCode】869. 找出一个数组的错乱(动态规划)

动态规划

设定状态: f[i] 表示含i个元素的排列能生成的错乱的数量

状态转移方程: f[i] = (i - 1) * (f[i-1] + f[i-2])

边界: f[1] = 0, f[2] = 1

对于 f[n] 的计算, 假定把 n 放到了第 k 个位置:

  • 这时如果把 k 放到了第 n 个位置, 那么剩下的 n-2 个元素的错乱即为 f[n-2]
  • 如果把 k 放到了其他位置, 也就是说 k 不能放到 n, 与 n-1 个元素的错乱中 "k不能放到k" 是等价的, 也就是说, 这时是 f[n-1]

k一共有 n-1 个选择, 故 f[n] = (i - 1) * (f[n-1] + f[n-2])

public class Solution {
    /**
     * @param n: an array consisting of n integers from 1 to n
     * @return: the number of derangement it can generate
     */
    public int findDerangement(int n) {
        if (n <= 1) {
            return 0;
        } 
        long[] dp = new long[n + 1];
        int mod = 1000000007;
        dp[2] = 1;
        for (int i=3; i < n + 1; i++) {
            dp[i] = (long) (i - 1) * (dp[i-2] + dp[i-1]) % mod;
        } 
        return (int)dp[n];
        
    }
}

 

你可能感兴趣的:(LintCode)