Problem overview
The function count_permutations takes n and returns the number of valley permutations of length n. A permutation of 1 through n is a valley when it is a decreasing run followed by an increasing run. Either run may be empty or have a single element. The statement limits N to 12.
For n = 4 the valley permutations are [1, 2, 3, 4], [2, 1, 3, 4], [3, 1, 2, 4], [3, 2, 1, 4], [4, 1, 2, 3], [4, 2, 1, 3], [4, 3, 1, 2] and [4, 3, 2, 1]. There are 8. The other 16 permutations of four numbers, such as [1, 3, 2, 4], go up and come back down, which a valley never does.
Approach: place the largest number at one end
In a valley, the values fall to a minimum and then rise. The smallest value, 1, is the bottom of the valley, and the largest value, i, can't be in the middle: a number with neighbours on both sides that are smaller would make a peak. So i must be at the very beginning or at the very end.
Remove it, and what is left is a valley permutation of length i - 1: taking an end element off a decreasing-then-increasing sequence leaves one. The step also reverses. Take any valley of length i - 1 and put i in front: the decreasing part just gets longer, or begins with it. Put i at the back, and the increasing part grows. Both results are valleys, and for i > 1 they are different permutations, since i is in different places. So each shorter permutation gives exactly two longer ones:
dp[i] = 2 * dp[i - 1]
Here is the step from length 2 to length 3. The valleys of length 2 are [1, 2] and [2, 1]. Putting 3 in front of each gives [3, 1, 2] and [3, 2, 1], and putting 3 at the back gives [1, 2, 3] and [2, 1, 3]. That is four valleys. The only two permutations of 1, 2, 3 left out are [1, 3, 2] and [2, 3, 1], which have 3 in the middle, and neither is a valley.
One detail makes the argument precise: removing the largest value leaves the other i - 1 values, which are exactly 1 through i - 1, so the remaining permutation is a plain permutation of that length and the same rule applies to it again.
The base case is dp[1] = 1: a single number is one valley. The table is 1, 2, 4, 8, matching the example: dp[4] = 8.
Step by step
- Answer
n = 0directly. Ifnis 0, return 1 with an explicitreturnand a semicolon, as an early exit needs. The empty permutation counts as a valley, since both of its runs are empty. The table below starts atdp[1], which doesn't exist whennis 0. - Create
dpwithvec![0i32; n + 1]. The starting code has already convertednto ausize. - Set
dp[1] = 1. - Loop over
2..=n. - Double:
dp[i] = 2 * dp[i - 1]. - Return
dp[n]as the final expression.
The solution in Rust
impl Solution {
fn count_permutations(n: i32) -> i32 {
let n = n as usize;
if n == 0 {
return 1;
}
let mut dp = vec![0i32; n + 1];
dp[1] = 1;
for i in 2..=n {
dp[i] = 2 * dp[i - 1];
}
dp[n]
}
}
The Rust details worth a closer look:
- Early
returnagainst the final expression. Thereturn 1;inside theifleaves the function at once. The last line,dp[n], has no semicolon, so it is the value returned otherwise. - Shadowing.
let n = n as usize;replaces thei32parameter with ausizeof the same name, which is the type vectors need for sizes and indices. - Overflow. The largest answer is
dp[12]= 2048, far below thei32limit. The table would overflow only atn = 32, where the value would be 2^31. - Why the guard matters. For
n = 0the vector has length 1, anddp[1] = 1would panic with an index out of bounds.
Complexity
Time: O(n). One multiplication per length.
Space: O(n). The table holds n + 1 entries. The answer is just 2^(n - 1) for n >= 1, but the table shows where it comes from.
Edge cases and common mistakes
- N = 0. Returns 1 from the guard.
- N = 1. Returns 1, and the loop is skipped.
- N = 2. Returns 2: [1, 2] is all increasing and [2, 1] is all decreasing, and both are valleys.
- Treating a single-run permutation as invalid. A fully increasing or fully decreasing permutation is a valley. One of the two parts is just empty.
- Counting all permutations. Using
i * dp[i - 1]counts every ordering and gives 24 forn = 4. - Placing the smallest number instead. The smallest number is the bottom of the valley and can sit at any position, so it gives no simple rule. The largest number is the one with only two possible places.
Testing
n = 0gives 1.n = 1gives 1.n = 2gives 2.n = 4gives 8.n = 12gives 2048.
