This problem asks to find the number of derangements of an array of integers from 1 to n, where a derangement is a permutation such that no element is in its original position. We'll explore two solutions: dynamic programming with and without space optimization.
This approach uses dynamic programming to efficiently calculate the number of derangements.
State Definition:
Let dp[i]
represent the number of derangements of an array of size i
.
Base Cases:
dp[0] = 1
(There's one way to derange an empty array)dp[1] = 0
(There's no way to derange an array of size 1)Recurrence Relation:
For an array of size i
, consider the placement of the element 1
. We have i-1
choices for its position.
1
in position j
, and then place j
in position 1
, we are left with i-2
elements to derange. This contributes (i-1) * dp[i-2]
derangements.1
in position j
, but don't place j
in position 1
, we have i-1
elements left to derange. This contributes (i-1) * dp[i-1]
derangements.Therefore, the recurrence relation is:
dp[i] = (i - 1) * (dp[i - 1] + dp[i - 2])
Algorithm:
dp[0]
and dp[1]
with base cases.i = 2
to n
, calculating dp[i]
using the recurrence relation.dp[n]
. Remember to take the modulo with 10^9 + 7
to handle large results.Time and Space Complexity:
dp
array once.dp
array.We observe that the recurrence relation only depends on the previous two values (dp[i-1]
and dp[i-2]
). Therefore, we can optimize space by only storing these two values instead of the entire array.
Algorithm:
a = 1
and b = 0
(representing dp[0]
and dp[1]
respectively).i = 2
to n
.c = (i - 1) * (a + b) % mod
.a = b
and b = c
.b
will hold the final result dp[n]
.Time and Space Complexity:
Approach 1:
class Solution:
def findDerangement(self, n: int) -> int:
mod = 10**9 + 7
dp = [1, 0] + [0] * (n - 1) # Initialize dp array
for i in range(2, n + 1):
dp[i] = (i - 1) * (dp[i - 1] + dp[i - 2]) % mod
return dp[n]
Approach 2:
class Solution:
def findDerangement(self, n: int) -> int:
mod = 10**9 + 7
a, b = 1, 0
for i in range(2, n + 1):
a, b = b, ((i - 1) * (a + b)) % mod
return b
The code in other languages (Java, C++, Go) follows similar logic, adapting the syntax and data types accordingly as shown in the original response. The space-optimized version is generally preferred due to its lower memory usage, especially for large values of n
.