3584. Maximum Product of First and Last Elements of a Subsequence
Problem Description
You are given an integer array nums
and an integer m
.
Return the maximum product of the first and last elements of any subsequence of nums
of size m
.
A subsequence is obtained by deleting zero or more elements from the array without changing the order of the remaining elements.
For every possible subsequence of length m
, consider the product of its first and last elements. The task is to find and return the maximum such product.
Intuition
To find the maximum product of the first and last elements of any subsequence of length m
, we need a way to efficiently check all possible pairs. By fixing the last element of the subsequence at position i
, the first element must come from one of the previous positions that keeps the gap at exactly m-1
. So, for each position i
, we look back at position i - m + 1
in nums
for possible first elements of valid subsequences ending at i
. By keeping track of the minimum and maximum values up to each of these starting positions, we can quickly calculate all possible products without searching all pairs every time, which makes the solution efficient and direct.
Solution Approach
The approach is to iterate over the array nums
and consider each position i
as the possible end (last element) of a subsequence of length m
. For each such ending position, the starting element of the subsequence must be at index i - m + 1
.
To efficiently find the maximum product, we maintain two variables:
mi
: the minimum value in the prefix ofnums
up to the position for possible starting elements,mx
: the maximum value in the prefix up to the same range.
For every ending position i
from m-1
to the end of the array, we:
- Update
mi
andmx
usingnums[i - m + 1]
(the current candidate for the starting element), - Compute the products
nums[i] * mi
andnums[i] * mx
, - Keep track of the maximum product found across all possible subsequences.
This ensures we only need to look at each possible subsequence once, and by updating the prefix min and max efficiently, the solution is optimized.
The main steps are:
- Initialize
ans
as negative infinity,mx
as negative infinity, andmi
as positive infinity. - Iterate from index
m-1
to the last index ofnums
. - For each index, update
mi
asmin(mi, nums[i - m + 1])
andmx
asmax(mx, nums[i - m + 1])
. - Calculate products:
nums[i] * mi
andnums[i] * mx
, then updateans
if these are larger. - Return
ans
at the end.
All calculations are done in a single pass for efficiency.
Ready to land your dream job?
Unlock your dream job with a 2-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Consider the input array nums = [3, -1, 4, 2, 5]
and m = 3
.
We need to find the maximum product of the first and last elements of any subsequence of length 3.
Letโs step through the approach:
- Initialize
ans = -โ
,mi = โ
,mx = -โ
. - We start checking at index
i = m-1 = 2
, up to index 4.
i | nums[i - m + 1] | Update mi/mx | nums[i] | Products candidate | Update ans |
---|---|---|---|---|---|
2 | nums[0]=3 | mi=3, mx=3 | 4 | 43=12, 43=12 | ans = 12 |
3 | nums[1]=-1 | mi=-1, mx=3 | 2 | 2*-1=-2, 2*3=6 | ans = 12 |
4 | nums[2]=4 | mi=-1, mx=4 | 5 | 5*-1=-5, 5*4=20 | ans = 20 |
Final answer: 20 (from the subsequence [3, 4, 5], product of first and last: 3 * 5 = 15, but the tracked max is from [4, 2, 5]: 4 * 5 = 20).
Step-by-Step
- At position 2, starting at 0: first=3, last=4, product=12.
- At position 3, starting at 1: first=-1, last=2, product=-2. Also try with previous max: 3*2=6.
- At position 4, starting at 2: first=4, last=5, product=20. Also try with previous min: -1*5=-5.
Thus, after one linear pass updating minimum and maximum starting values, the largest product is found efficiently.
Solution Implementation
1from typing import List
2
3class Solution:
4 def maximumProduct(self, nums: List[int], m: int) -> int:
5 """
6 Given an integer list 'nums' and an integer 'm', find the maximum product
7 that can be formed by multiplying the current element at index 'i' (where i >= m-1)
8 with either the minimum or maximum among the potential start elements of a window of size 'm' ending at 'i'.
9 """
10
11 # Initialize the answer as negative infinity for maximization.
12 max_product = float('-inf')
13 # Track the minimum value seen so far among window start elements.
14 min_value = float('inf')
15 # Track the maximum value seen so far among window start elements.
16 max_value = float('-inf')
17
18 # Loop through each end of a window of size m
19 for end in range(m - 1, len(nums)):
20 current = nums[end] # Current window's end element
21 window_start = nums[end - m + 1] # Current window's start element
22
23 # Update min and max values among the window start elements
24 min_value = min(min_value, window_start)
25 max_value = max(max_value, window_start)
26
27 # Check the product with the window's possible min and max starts
28 max_product = max(max_product, current * min_value, current * max_value)
29
30 return max_product
31
1class Solution {
2 public long maximumProduct(int[] nums, int m) {
3 long maxProduct = Long.MIN_VALUE; // Variable to keep track of the maximum product
4 int maxInWindow = Integer.MIN_VALUE; // Maximum number in the current sliding window
5 int minInWindow = Integer.MAX_VALUE; // Minimum number in the current sliding window
6
7 // Iterate starting from the end of the first window (size m)
8 for (int i = m - 1; i < nums.length; ++i) {
9 int right = nums[i]; // Current element (right end of the window)
10 int left = nums[i - m + 1]; // New leftmost element entering the window
11
12 // Update minInWindow and maxInWindow with the new left element
13 minInWindow = Math.min(minInWindow, left);
14 maxInWindow = Math.max(maxInWindow, left);
15
16 // Calculate possible products with min and max values, update maxProduct
17 long productWithMin = 1L * right * minInWindow;
18 long productWithMax = 1L * right * maxInWindow;
19 maxProduct = Math.max(maxProduct, Math.max(productWithMin, productWithMax));
20 }
21 return maxProduct;
22 }
23}
24
1#include <vector>
2#include <climits>
3using namespace std;
4
5class Solution {
6public:
7 long long maximumProduct(vector<int>& nums, int m) {
8 long long maxProduct = LLONG_MIN; // Tracks the answer (maximum product found)
9 int currMax = INT_MIN; // Largest value in the current window
10 int currMin = INT_MAX; // Smallest value in the current window
11
12 // Iterate through the array, considering every window of size m that ends at i
13 for (int i = m - 1; i < nums.size(); ++i) {
14 int rightmost = nums[i]; // Current element at the end of the window
15 int leftmost = nums[i - m + 1]; // Current element at the start of the window
16
17 currMin = min(currMin, leftmost); // Update current minimum in the window
18 currMax = max(currMax, leftmost); // Update current maximum in the window
19
20 // Compute two possible products with min and max and update maxProduct
21 maxProduct = max(maxProduct, max(1LL * rightmost * currMin, 1LL * rightmost * currMax));
22 }
23 return maxProduct;
24 }
25};
26
1/**
2 * Finds the maximum product of any two numbers in the array,
3 * where the second number is within the last `m` elements before or at the current index.
4 * @param nums - Array of integers.
5 * @param m - The window size.
6 * @returns The maximum product found.
7 */
8function maximumProduct(nums: number[], m: number): number {
9 // Initialize the answer to the smallest possible safe integer.
10 let result = Number.MIN_SAFE_INTEGER;
11
12 // Track the minimum and maximum values within the current window.
13 let maxInWindow = Number.MIN_SAFE_INTEGER;
14 let minInWindow = Number.MAX_SAFE_INTEGER;
15
16 // Traverse the array, starting from index (m - 1) to ensure a full window.
17 for (let i = m - 1; i < nums.length; i++) {
18 const current = nums[i]; // Current number.
19 const windowStart = nums[i - m + 1]; // Start of the current window (sliding).
20
21 // Update the minimum and maximum with the new window start value.
22 minInWindow = Math.min(minInWindow, windowStart);
23 maxInWindow = Math.max(maxInWindow, windowStart);
24
25 // Calculate product of the current number with the current min and max in the window.
26 // Update the result if a larger product is found.
27 result = Math.max(result, current * minInWindow, current * maxInWindow);
28 }
29
30 return result;
31}
32
Time and Space Complexity
The time complexity is O(n)
, where n
is the length of the array nums
. This is because the single loop iterates over each relevant element of nums
exactly once.
The space complexity is O(1)
, as only a fixed number of variables (ans
, mx
, mi
, x
, y
) are used regardless of the input size.
Which type of traversal does breadth first search do?
Recommended Readings
Tech Interview Pattern Two Pointers Introduction If you prefer videos here's a super quick introduction to Two Pointers div class responsive iframe iframe src https www youtube com embed xZ4AfXHQ1VQ title YouTube video player frameborder 0 allow accelerometer autoplay clipboard write encrypted media gyroscope picture in picture allowfullscreen iframe div Two pointers is a common interview
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Want a Structured Path to Master System Design Too? Donโt Miss This!