You are given three integers n
, m
and k
. Consider the following algorithm to find the maximum element of an array of positive integers:
Algorithm:
search_cost = 0
max_so_far = arr[0]
for i = 1 to arr.length - 1:
if arr[i] > max_so_far:
max_so_far = arr[i]
search_cost = search_cost + 1
return search_cost
You should build the array arr
which has the following properties:
arr
has exactly n
integers.1 <= arr[i] <= m
where (0 <= i < n)
. That is, each element arr[i]
can be any integer between 1 and m inclusive.arr
, the value search_cost
is equal to k
.Return the number of ways to build the array arr
under the mentioned conditions. As the answer may grow large, the answer must be computed modulo 10^9 + 7
.
Example 1:
n = 2, m = 3, k = 1
Output: 6
Explanation: The possible arrays are [1, 2], [1, 3], [2, 3], [2, 1], [3, 1], [3, 2]. Note that [1,1], [2,2], [3,3] are not valid since the search_cost would be 0.
Example 2:
n = 5, m = 2, k = 3
Output: 0
Explanation: There are no possible arrays that satisfy the mentioned conditions.
Example 3:
n = 9, m = 1, k = 1
Output: 1
Explanation: The only possible array is [1, 1, 1, 1, 1, 1, 1, 1, 1]
Constraints:
1 <= n <= 50
1 <= m <= 100
0 <= k <= n
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The brute force approach solves this by checking every single possible array we could make. It's like trying every combination of building blocks until we find one that fits our requirements exactly.
Here's how the algorithm would work step-by-step:
def build_array_brute_force(array_length, max_value, target_comparisons):
valid_array_count = 0
def comparison_count(array):
comparison_amount = 0
if not array:
return 0
maximum_value = array[0]
for i in range(1, len(array)):
if array[i] > maximum_value:
maximum_value = array[i]
comparison_amount += 1
return comparison_amount
def generate_arrays(current_array):
nonlocal valid_array_count
if len(current_array) == array_length:
# Check if the array matches the conditions
if comparison_count(current_array) == target_comparisons:
valid_array_count += 1
return
# Explore possibilities by adding values to the array
for value in range(1, max_value + 1):
generate_arrays(current_array + [value])
# Start the recursive process
generate_arrays([])
return valid_array_count
This problem seems tricky, but the best way to tackle it is using a clever method called dynamic programming. We break down the big problem into smaller, overlapping subproblems, and store the answers to these subproblems to avoid recalculating them later. This avoids trying every single possibility, making the solution much faster.
Here's how the algorithm would work step-by-step:
def build_array(array_length, max_value, target_cost):
modulo = 10**9 + 7
# Initialize a DP table to store results of subproblems
dp_table = [[[0] * (target_cost + 1) for _ in range(max_value + 1)] for _ in range(array_length + 1)]
dp_table[0][0][0] = 1
for current_length in range(1, array_length + 1):
for current_max in range(1, max_value + 1):
for current_cost in range(target_cost + 1):
# If we don't introduce a new max value
dp_table[current_length][current_max][current_cost] += (dp_table[current_length - 1][current_max][current_cost] * current_max) % modulo
dp_table[current_length][current_max][current_cost] %= modulo
# If we introduce a new max value
if current_cost > 0:
# Adding a new max increases the search cost
for previous_max in range(1, current_max):
dp_table[current_length][current_max][current_cost] += dp_table[current_length - 1][previous_max][current_cost - 1]
dp_table[current_length][current_max][current_cost] %= modulo
result = 0
# Sum up all possibilities where the max value is achieved
for current_max in range(1, max_value + 1):
result += dp_table[array_length][current_max][target_cost]
result %= modulo
return result
Case | How to Handle |
---|---|
n = 0, m > 0, k > 0 (invalid input) | Return 0 since an empty array cannot satisfy the conditions for k > 0. |
n > 0, m = 0, k > 0 (invalid input) | Return 0 since there are no possible values that would result in k comparisons. |
n > 0, m > 0, k = 0 (invalid input) | Return 0, because it's impossible to find the maximum with zero comparisons. |
n > 0, m > 0, k > n (invalid input - k exceeds the possible comparisons) | Return 0 since at most n-1 comparisons can be made to determine the maximum. |
n > 0, m = 1, k = 1 (Only one value allowed and we must find the max with 1 comparison) | Return 1, since the only possible array contains all 1's, and the first element is the max after one comparison |
Large n and m values causing potential integer overflow during calculation. | Use modular arithmetic during calculation and ensure intermediate values don't exceed the integer limit. |
m < 1 and k >= 1 (invalid input range for m) | Return 0, as m must be at least 1 to create valid elements in the array. |
n=1, k=1, m>0 (array of size 1, k=1 comparison) | Return m since only one comparison is needed and the first element is the maximum |