Problem overview
The method countPermutations receives an Int n and returns the number of valley permutations of length n. A permutation of length n uses each of the numbers 1 to n exactly once. It is a valley permutation if it is a decreasing run followed by an increasing run, so its values fall to a lowest point and then rise.
For n = 4 the answer is 8: [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]. Either run may be empty or have a single element, so a fully increasing or fully decreasing permutation also counts. The statement guarantees n is at most 12.
Among the 24 permutations of length 4, only these 8 have the valley shape. Checking each permutation would work for small n but gets slow quickly, so the lesson finds a rule that counts them directly.
Approach: where can the largest number go?
Look at the position of the largest number, i, in a valley permutation of length i. Inside the decreasing run, every element is smaller than the one before it, so a large element must come at the start. Inside the increasing run, every element is larger than the one before it, so a large element must come at the end. The largest number can therefore only be the first element or the last element.
Removing it from either end leaves a valley permutation of length i - 1: the remaining elements still fall and then rise. In the other direction, take any valley permutation of length i - 1 and place the new largest number at the front or at the back. Both results are valley permutations of length i, and they are different permutations. So each shorter permutation gives exactly two longer ones, and every longer one arises this way:
count(i) = 2 * count(i - 1)
The base case is count(1) = 1, since the permutation [1] is the only one. That gives 1, 2, 4, 8, ... , which matches the 8 listed for n = 4. The table is a short way to record each step of that argument.
Step by step
- Handle
n = 0first. Ifnis 0, return 1. The empty permutation is the only permutation of length 0, and it counts as a valley permutation because both of its runs are empty. The table below starts fromdp(1), which exists only whennis at least 1, so this case is answered directly. - Create the table.
dpis anArray[Int]of lengthn + 1filled with zeros usingArray.fill(n + 1)(0). Entryiwill hold the number of valley permutations of lengthi. - Set the base case.
dp(1) = 1, since one number forms exactly one permutation. - Loop over the lengths.
i <- 2 to nvisits each length from 2 up ton, andtoincludesn. - Apply the recurrence.
dp(i) = 2 * dp(i - 1): the largest number goes first or last. - Return
dp(n).
The solution in Scala
class Solution {
def countPermutations(n: Int): Int = {
if (n == 0) {
return 1
}
val dp = Array.fill(n + 1)(0)
dp(1) = 1
for (i <- 2 to n) {
dp(i) = 2 * dp(i - 1)
}
return dp(n)
}
}
The Scala details worth a closer look:
Array.fill(n + 1)(0). It has two parameter lists. The first is the size and the second is the value to repeat, so the call builds anArray[Int]ofn + 1zeros.new Array[Int](n + 1)would give the same array.- The early
return. A Scala method normally returns its last expression, butreturnis the simplest way to leave early. Without the guard,dp(1) = 1would throw anArrayIndexOutOfBoundsExceptionforn = 0, because the array has only index 0. valfixes the name, not the elements.dpis aval, butdp(i) = ...changes an element of the array it refers to.- Round brackets and ranges. Array elements are read as
dp(i). In2 to n, the end is included. Whennis 1, the range2 to 1is empty and the loop does nothing. - Size of the answer. The result is
2to the powern - 1, which forn = 12is 2,048. That is far below the limit of anInt, which is about 2.1 billion.
Complexity
Time: O(n). The loop runs at most n - 1 times and each pass does one multiplication.
Space: O(n). The table has n + 1 entries. Since each entry depends only on the previous one, a single variable would reduce the space to O(1).
Edge cases and common mistakes
n = 0. The guard returns 1 for the empty permutation.n = 1. The loop is skipped anddp(1)is 1.n = 2. Both[1, 2]and[2, 1]are valleys, so the answer is 2.n = 3. The answer is 4. Among the six permutations of 1, 2, 3, the ones that fail are[1, 3, 2]and[2, 3, 1], which rise and then fall, the opposite of a valley.- Confusing valleys with all permutations. Multiplying by
iinstead of by 2 counts every permutation, which gives 24 forn = 4instead of 8. - Forgetting the end positions. Counting only one end, for example putting the largest number first, halves every answer.
Testing
n = 0gives1.n = 1gives1.n = 2gives2.n = 3gives4.n = 4gives8.n = 12gives2048.
