Facebook Pixel

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.

Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

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 of nums 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 and mx using nums[i - m + 1] (the current candidate for the starting element),
  • Compute the products nums[i] * mi and nums[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:

  1. Initialize ans as negative infinity, mx as negative infinity, and mi as positive infinity.
  2. Iterate from index m-1 to the last index of nums.
  3. For each index, update mi as min(mi, nums[i - m + 1]) and mx as max(mx, nums[i - m + 1]).
  4. Calculate products: nums[i] * mi and nums[i] * mx, then update ans if these are larger.
  5. 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 Evaluator

Example 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:

  1. Initialize ans = -โˆž, mi = โˆž, mx = -โˆž.
  2. We start checking at index i = m-1 = 2, up to index 4.
inums[i - m + 1]Update mi/mxnums[i]Products candidateUpdate ans
2nums[0]=3mi=3, mx=3443=12, 43=12ans = 12
3nums[1]=-1mi=-1, mx=322*-1=-2, 2*3=6ans = 12
4nums[2]=4mi=-1, mx=455*-1=-5, 5*4=20ans = 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.


Discover Your Strengths and Weaknesses: Take Our 2-Minute Quiz to Tailor Your Study Plan:

Which type of traversal does breadth first search do?


Recommended Readings

Want a Structured Path to Master System Design Too? Donโ€™t Miss This!

Load More