Given two arrays nums1 and nums2.
Return the maximum dot product between non-empty subsequences of nums1 and nums2 with the same length.
A subsequence of a array is a new array which is formed from the original array by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie, [2,3,5] is a subsequence of [1,2,3,4,5] while [1,5,3] is not).
Example 1:
Input: nums1 = [2,1,-2,5], nums2 = [3,0,-6] Output: 18 Explanation: Take subsequence [2,-2] from nums1 and subsequence [3,-6] from nums2. Their dot product is (2*3 + (-2)*(-6)) = 18.
Example 2:
Input: nums1 = [3,-2], nums2 = [2,-6,7] Output: 21 Explanation: Take subsequence [3] from nums1 and subsequence [7] from nums2. Their dot product is (3*7) = 21.
Example 3:
Input: nums1 = [-1,-1], nums2 = [1,1] Output: -1 Explanation: Take subsequence [-1] from nums1 and subsequence [1] from nums2. Their dot product is -1.
Constraints:
1 <= nums1.length, nums2.length <= 500-1000 <= nums1[i], nums2[i] <= 1000When 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 method to find the maximum dot product between subsequences involves checking every possible combination. We need to explore all possible subsequences from both input sequences and calculate their dot product. The best (maximum) dot product is then selected from all these options.
Here's how the algorithm would work step-by-step:
def max_dot_product_brute_force(first_array, second_array):
max_dot_product = float('-inf')
def get_all_subsequences(input_array):
subsequences = [[]]
for number in input_array:
new_subsequences = [subsequence + [number] for subsequence in subsequences]
subsequences.extend(new_subsequences)
return subsequences
first_array_subsequences = get_all_subsequences(first_array)
second_array_subsequences = get_all_subsequences(second_array)
for first_subsequence in first_array_subsequences:
for second_subsequence in second_array_subsequences:
# We only calculate dot products for subsequences of equal length.
if len(first_subsequence) == len(second_subsequence):
if not first_subsequence or not second_subsequence:
dot_product = 0
else:
dot_product = sum(first_subsequence[i] * second_subsequence[i] for i in range(len(first_subsequence)))
# Update the maximum dot product if the current dot product is greater
max_dot_product = max(max_dot_product, dot_product)
# Need to handle edge case if both arrays contain only negative numbers.
if max_dot_product == 0 and (all(number < 0 for number in first_array) or all(number < 0 for number in second_array)):
max_first = max(first_array) if first_array else float('-inf')
max_second = max(second_array) if second_array else float('-inf')
if max_first != float('-inf') and max_second != float('-inf'):
max_dot_product = max(max_dot_product, max_first * max_second)
elif max_first != float('-inf'):
max_dot_product = max(max_dot_product, max_first)
elif max_second != float('-inf'):
max_dot_product = max(max_dot_product, max_second)
else:
max_dot_product = float('-inf')
return max_dot_productWe want to find the largest possible score from multiplying matching parts of two sequences. The clever approach is to build up the solution step by step, remembering the best score we can achieve at each point. This avoids recomputing the same things over and over again.
Here's how the algorithm would work step-by-step:
def max_dot_product(first_sequence, second_sequence):
first_sequence_length = len(first_sequence)
second_sequence_length = len(second_sequence)
# Initialize the DP table with zeros.
dot_product_table = [([0] * (second_sequence_length + 1)) for _ in range(first_sequence_length + 1)]
for i in range(1, first_sequence_length + 1):
for j in range(1, second_sequence_length + 1):
#Consider excluding nums1[i-1] or nums2[j-1].
exclude_first_sequence = dot_product_table[i - 1][j]
exclude_second_sequence = dot_product_table[i][j - 1]
#Consider including both nums1[i-1] and nums2[j-1].
include_both_sequences = dot_product_table[i - 1][j - 1] + (first_sequence[i - 1] * second_sequence[j - 1])
#If both elements are negative.
only_these_elements = first_sequence[i - 1] * second_sequence[j - 1]
dot_product_table[i][j] = max(exclude_first_sequence, exclude_second_sequence, include_both_sequences, only_these_elements)
return dot_product_table[first_sequence_length][second_sequence_length]| Case | How to Handle |
|---|---|
| Both input arrays are empty | Return 0 as the dot product of two empty subsequences is defined as 0. |
| One array is empty, the other is not | Return negative infinity because the dot product must be computed using sub-sequences from each array. |
| Arrays with a single element each, and both elements are negative | Return the product of the two negative single elements (which will be positive or zero). |
| Arrays with a single element each, one positive and the other negative | Return the product of the two elements which would be negative. |
| Arrays with all positive numbers | The optimal subsequence will likely be the entire array, so the solution should effectively handle the full array length. |
| Arrays with all negative numbers | The optimal subsequence will be the two largest negative numbers in each array, therefore consider single elements. |
| Integer overflow during multiplication of large numbers | Use long data type to store intermediate results to avoid overflow when calculating the dot product. |
| Arrays with a mix of positive, negative, and zero values | The algorithm must correctly account for zero values and negative values when determining the maximum dot product. |