1855. Maximum Distance Between a Pair of Values
Problem Description
In this problem, we are given two non-increasing integer arrays, nums1
and nums2
. We define a valid pair as a pair of indices (i, j)
such that:
i
is an index fromnums1
andj
is an index fromnums2
.i
must be less than or equal toj
(i <= j
).- The value at
nums1[i]
must be less than the value atnums2[j]
(nums1[i] < nums2[j]
).
The distance for a valid pair (i, j)
is calculated by the difference j - i
. The goal of the problem is to return the maximum possible distance for any valid pair of indices. If there are no valid pairs, we should return 0
.
Note that an array is non-increasing if each element is less than or equal to the previous element. This implies that the numbers in both nums1
and nums2
are sorted in non-increasing order (from largest to smallest).
Intuition
The intuition behind the solution involves recognizing that if a pair (i, j)
is valid, then any pair (i, k)
where k < j
is also valid due to the non-increasing order of the arrays. This property allows us to use a two-pointer or a binary search approach to efficiently find the maximum distance. We choose the two-pointer approach here as it simplifies the implementation.
We start by initializing two pointers, i
and j
, at the beginning of nums1
and nums2
respectively. We then iterate through nums1
with i
, trying to find the furthest j
in nums2
that will form a valid pair. As we go, we keep track of the maximum distance ans
.
The crucial observation is that since both nums1
and nums2
are non-increasing, once we find a j
for a particular i
such that nums1[i] <= nums2[j]
, we don't need to reset j
back to i
for the next i
. Instead, we can continue from the current j
, because if nums1[i] <= nums2[j]
and nums1
is non-increasing, then nums1[i + 1]
will be less than or equal to nums1[i]
, and hence also less than or equal to nums2[j]
. We keep incrementing j
until the condition nums1[i] <= nums2[j]
is no longer met.
However, we need to calculate the distance j - i
and store the maximum. Since j
is incremented in the inner loop until nums1[i] <= nums2[j]
is false, at this point j
is actually one index past the valid pair, so we compute j - i - 1
to get the correct distance for considering the current index i
.
As a result, the algorithm efficiently calculates the maximum distance of any valid pair by scanning through both arrays only once.
Learn more about Greedy, Two Pointers and Binary Search patterns.
Solution Approach
The given reference solution approach indicates using a Binary Search algorithm. However, the provided solution code actually uses a two-pointer technique, which intuitively exploits the sorted nature of the arrays to find the maximum distance. Below, we'll walk through the implementation of the two-pointer solution given in the code.
The code defines a class Solution
with a method maxDistance
which accepts two arrays, nums1
and nums2
.
-
Initialization: We begin by initializing a few variables:
m
, the length ofnums1
n
, the length ofnums2
ans
, which will keep track of the maximum distance found among valid pairs. It is set to0
initially.- Two pointers
i
andj
, both set to0
, to iterate throughnums1
andnums2
respectively.
-
Iterating with Two Pointers: We use a while loop to iterate through
nums1
withi
as long asi < m
(ensuring we don't go out of bounds). -
Finding the Furthest
j
: For every indexi
, we have an inner while loop that seeks the furthestj
such thatnums1[i] <= nums2[j]
. This loop runs as long asj < n
. If the condition is met,j
is incremented by1
, moving the second pointer ahead innums2
. -
Tracking the Maximum Distance: Once we are either out of bounds in
nums2
or the condition is no longer satisfied, the inner loop breaks and we use the maximum functionmax(ans, j - i - 1)
to update our answer with the largest distance found so far. The-1
is there to correct for thej
index that is now at an invalid pair, having just moved past the last validnums2[j]
. -
Incrementing
i
: After checking and possibly updating theans
with the maximum distance for the currenti
, we incrementi
by1
and repeat the above steps until all elements ofnums1
have been considered. -
Returning the Answer: When the loop terminates,
ans
will hold the maximum distance of any valid pair(i, j)
, or it will remain0
if no valid pairs existed. This value is then returned as the result of the method.
The two-pointer approach is efficient because it leverages the sorted properties of nums1
and nums2
to avoid redundant checks. It doesn't require additional data structures and runs in linear time, as each pointer only passes through its respective array once.
Thus, the implementation uses a methodical two-pointer strategy to measure the maximum distance between valid pairs across two sorted arrays.
Ready to land your dream job?
Unlock your dream job with a 2-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through an example to illustrate the solution approach in practice.
Suppose we have the following inputs:
nums1 = [4, 2, 2]
nums2 = [3, 2, 0]
We want to find the maximum possible distance for any valid pair of indices.
-
We start with
i = 0
innums1
andj = 0
innums2
, withans = 0
as we haven't found any valid pairs yet. -
In the outer loop,
i
is now at index0
andnums1[0]
is4
. The inner while loop starts iteratingj
throughnums2
.nums2[j]
is3
, which is less thannums1[i]
, so we don't have a valid pair. We continue to the nextj
without changingans
. -
Now,
j = 1
andnums2[j]
is2
. It's still not greater thannums1[i] = 4
, so we move to the nextj
. -
At
j = 2
, we havenums2[j]
equal to0
, which is also not greater than4
. Having reached the end ofnums2
without finding a valid pair fori = 0
, we incrementi
to1
and start over withj = 0
. -
Now
i = 1
andnums1[i]
is2
. Starting again from the beginning ofnums2
, we find thatnums2[0]
is3
, which is greater thannums1[1]
. This is a valid pair(i=1, j=0)
. Hence, we updateans = max(ans, 0 - 1 - 1)
, but this gives us-2
, which is not an increase over0
, soans
stays at0
. -
We increment
j
to see if there is a pair with a larger distance. Nowj
is1
and sincenums1[i] = 2
is already less thannums2[j] = 2
, we stop the inner while loop and updateans
. Nowans = max(0, 1 - 1 - 1)
, which remains0
as the indices are the same. -
Finally, we increment
i
to2
.nums1[i]
is still2
, and we try withnums2[j]
starting from the beginning. Atj = 0
, we once again have a valid pair(i=2, j=0)
and updateans
tomax(0, 0 - 2 - 1)
, giving us-3
, which doesn't increaseans
. Since all values are non-increasing and there's no greater element innums2
than3
, we can conclude there's no need to iteratej
further fori = 2
.
After considering all elements of nums1
and finding no valid pair with a positive distance, the function returns the ans
, which in this case remains 0
as there were no valid pairs that satisfied the condition for a positive maximum distance.
This example demonstrates how the two-pointer approach navigates through both arrays, cleverly using the condition of non-increasing order to find the valid pairs and calculating the maximum possible distance.
Solution Implementation
1# Import the List type from the typing module for type annotations
2from typing import List
3
4class Solution:
5 def maxDistance(self, nums1: List[int], nums2: List[int]) -> int:
6 # Initialize the lengths of the two input lists
7 len_nums1, len_nums2 = len(nums1), len(nums2)
8
9 # Initialize the maximum distance and the indices for nums1 and nums2
10 max_distance = idx_nums1 = idx_nums2 = 0
11
12 # Loop through the elements of nums1
13 while idx_nums1 < len_nums1:
14 # For the current idx_nums1, increase idx_nums2 as long as
15 # the conditions are satisfied (nums1[idx_nums1] <= nums2[idx_nums2])
16 while idx_nums2 < len_nums2 and nums1[idx_nums1] <= nums2[idx_nums2]:
17 idx_nums2 += 1
18 # Update the maximum distance if a larger one is found
19 # Decrement by 1 because idx_nums2 is increased one more time before the condition fails
20 max_distance = max(max_distance, idx_nums2 - idx_nums1 - 1)
21 # Move to the next index in nums1
22 idx_nums1 += 1
23
24 # Return the maximum distance found
25 return max_distance
26
1class Solution {
2 public int maxDistance(int[] nums1, int[] nums2) {
3 int lengthNums1 = nums1.length; // length of the first array
4 int lengthNums2 = nums2.length; // length of the second array
5 int maxDist = 0; // variable to keep track of the maximum distance
6
7 // Initialize two pointers for both arrays
8 for (int indexNums1 = 0, indexNums2 = 0; indexNums1 < lengthNums1; ++indexNums1) {
9 // Move the indexNums2 pointer forward as long as the condition holds
10 while (indexNums2 < lengthNums2 && nums1[indexNums1] <= nums2[indexNums2]) {
11 ++indexNums2;
12 }
13 // Update maxDist with the maximum distance found so far
14 // We subtract 1 because indexNums2 has moved one step further than the true distance
15 maxDist = Math.max(maxDist, indexNums2 - indexNums1 - 1);
16 }
17 return maxDist; // return the maximum distance found
18 }
19}
20
1class Solution {
2public:
3 int maxDistance(vector<int>& nums1, vector<int>& nums2) {
4 int nums1Size = nums1.size(); // Represents the size of the first vector nums1
5 int nums2Size = nums2.size(); // Represents the size of the second vector nums2
6 int maxDist = 0; // Initialize maximum distance to 0
7
8 // Using two pointers, iterate through both arrays
9 // i is the pointer for nums1 and j is the pointer for nums2
10 for (int i = 0, j = 0; i < nums1Size; ++i) {
11 // While j is within the bounds of nums2 and the value at nums1[i]
12 // is less than or equal to the value at nums2[j], increment j
13 while (j < nums2Size && nums1[i] <= nums2[j]) {
14 ++j;
15 }
16 // Calculate the current distance, and update maxDist if it's greater
17 // than the current maxDist. Subtract one because j has been incremented
18 // in the last iteration of the inner loop where the condition was still valid.
19 maxDist = max(maxDist, j - i - 1);
20 }
21
22 return maxDist; // Return the computed maximum distance
23 }
24};
25
1function maxDistance(nums1: number[], nums2: number[]): number {
2 let maximumDistance = 0; // This will store the maximum distance found.
3 const nums1Length = nums1.length; // Length of the first array
4 const nums2Length = nums2.length; // Length of the second array
5
6 // Start with two pointers, 'i' for array nums1 and 'j' for array nums2
7 for (let i = 0, j = 0; i < nums1Length; ++i) {
8 // Increment 'j' as long as it's within the bounds of nums2
9 // and the element in nums1 is less than or equal to the element in nums2.
10 // This ensures that the 'j' finds the furthest distance it can go for each 'i'.
11 while (j < nums2Length && nums1[i] <= nums2[j]) {
12 j++;
13 }
14
15 // Update the maximum distance. Since 'j' moved one step extra, we subtract 1.
16 // i.e., j - i is the total distance from current 'i' to the last valid 'j'
17 // but we need to subtract 1 since 'j' has moved one step ahead of valid position.
18 maximumDistance = Math.max(maximumDistance, j - i - 1);
19 }
20
21 // Return the maximum distance found
22 return maximumDistance;
23}
24
Time and Space Complexity
Time Complexity
The time complexity of the given code is O(m + n)
. Here, m
is the length of nums1
and n
is the length of nums2
. This is because the two pointers i
and j
only move forward through their respective arrays, with i
incrementing in every outer loop, and j
potentially moving forward during each inner loop until nums1[i] <= nums2[j]
no longer holds. Since each pointer goes through its respective array at most once, the time complexity is linear with respect to the sizes of the input arrays.
Space Complexity
The space complexity of the code is O(1)
. No additional space is used that grows with the input size. The variables ans
, i
, j
, m
, and n
each use a constant amount of space.
Learn more about how to find time and space complexity quickly using problem constraints.
What's the relationship between a tree and a graph?
Recommended Readings
Greedy Introduction div class responsive iframe iframe src https www youtube com embed WTslqPbj7I title YouTube video player frameborder 0 allow accelerometer autoplay clipboard write encrypted media gyroscope picture in picture web share allowfullscreen iframe div When do we use greedy Greedy algorithms tend to solve optimization problems Typically they will ask you to calculate the max min of some value Commonly you may see this phrased in the problem as max min longest shortest largest smallest etc These keywords can be identified by just scanning
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
Binary Search Speedrun For each of the Speedrun questions you will be given a binary search related problem and a corresponding multiple choice question The multiple choice questions are related to the techniques and template s introduced in the binary search section It's recommended that you have gone through at
Want a Structured Path to Master System Design Too? Don’t Miss This!