624. Maximum Distance in Arrays
Problem Description
In this problem, we are provided m
separate arrays, each being sorted in ascending order. Our task is to find the maximum distance between any two integers where each integer is taken from a different array. The distance is defined as the absolute difference between those two integers. That is, if we take one integer a
from one array and another integer b
from a different array, the distance is |a - b|
. We need to compute and return the maximum such distance possible.
Intuition
To solve this problem efficiently, we leverage the fact that each of the m
arrays is sorted in ascending order. Given this property, the smallest element of each array will be at the 0-th index and the largest element at the last index.
To find the maximum distance, we need to make the difference as large as possible. This means we should consider the potential largest distance by taking the smallest element from one array and the largest from another array. So to maximize the distance, we always consider the minimum element from one array and the maximum element from the other.
The approach is to iterate through the arrays while tracking the smallest and largest elements we have seen so far. For each new array, we consider the distance between the current array's smallest element and the maximum element seen so far, and vice versa - the distance between the current array's largest element and the smallest element seen so far. The answer is the largest of all these distances.
Here is the step-by-step reasoning:
- Initialize
ans
to 0, which will keep track of the maximum distance. - Take the smallest (
mi
) and largest (mx
) elements from the first array to initiate tracking. - Iterate through the remaining arrays starting from the second one. For each array:
- Calculate the absolute difference between the current array's smallest element and
mx
(the largest element seen so far). - Calculate the absolute difference between the current array's largest element and
mi
(the smallest element seen so far). - Update
ans
with the largest value betweenans
, the first calculated difference, and the second calculated difference. - Update
mi
with the smallest value betweenmi
(the smallest value found so far) and the smallest element of the current array. - Update
mx
with the largest value betweenmx
(the largest value found so far) and the largest element of the current array.
- Calculate the absolute difference between the current array's smallest element and
- After finishing the iteration, return
ans
as the maximum distance found.
By only comparing the extreme ends of each array, we ensure that we are always considering the likely pairs to give us the maximum distance while maintaining a linear time complexity.
Learn more about Greedy patterns.
Solution Approach
The solution follows a greedy strategy by keeping track of the smallest and the largest element found so far across all arrays. Here is how the implementation reflects the approach:
- An initial answer
ans
is set to 0, which will hold the maximum distance. - The smallest element
mi
and the largest elementmx
from the first array are used to initialize the tracking. - Then, for every subsequent array, the implementation performs the following steps:
- Calculates two distances: the distance between the smallest element of the current array and the largest element
mx
seen so far (a = abs(arr[0] - mx)
), and the distance between the largest element of the current array and the smallest elementmi
seen so far (b = abs(arr[-1] - mi)
). - The answer
ans
is updated to be the maximum ofans
,a
, andb
. - The current array's smallest element is considered to update
mi
usingmi = min(mi, arr[0])
if it is smaller than the currentmi
. - Similarly, the current array's largest element is used to update
mx
usingmx = max(mx, arr[-1])
if it is larger than the currentmx
.
- Calculates two distances: the distance between the smallest element of the current array and the largest element
By using min()
and max()
functions, the elements mi
and mx
are continuously updated to always represent the smallest and largest element found up to the current point in iteration.
This approach guarantees each array is only visited once, making the overall time complexity O(m)
, where m
is the number of arrays. There is no use of additional data structures, keeping space complexity to O(1)
as it only uses a few variables for tracking the minimum, maximum, and the current answer.
The code directly follows this strategy and does not use any complex data structures or algorithms beyond basic conditional statements and math operations.
Here's a snippet of the main logic using the algorithm described:
class Solution:
def maxDistance(self, arrays: List[List[int]]) -> int:
ans = 0
mi, mx = arrays[0][0], arrays[0][-1]
for arr in arrays[1:]:
a, b = abs(arr[0] - mx), abs(arr[-1] - mi)
ans = max(ans, a, b)
mi = min(mi, arr[0])
mx = max(mx, arr[-1])
return ans
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 say we have the following 3 sorted arrays:
- Array 1:
[1, 2, 3]
- Array 2:
[4, 5]
- Array 3:
[1, 5, 9]
Our goal is to find the maximum distance between any two integers from two different arrays.
- Initialize
ans
to 0, which will be used to keep track of the maximum distance found so far. - We start with the first array and take its smallest and largest elements as the initial values for
mi
andmx
respectively. In this case,mi
is1
andmx
is3
.
Now, we iterate through the remaining arrays to calculate potential distances and update mi
and mx
.
-
Moving to the second array
[4, 5]
, we calculate the distance between the smallest element in this array4
and the currentmx
3
which isabs(4 - 3) = 1
. We also calculate the distance between the largest element in this array5
and the currentmi
1
which isabs(5 - 1) = 4
. We updateans
to the maximum ofans
, which is0
, and these new distances.ans
is now4
. We also updatemi
andmx
if necessary. Since4
is greater thanmi
and5
is greater thanmx
, we only updatemx
to5
. -
Next, we go to the third array
[1, 5, 9]
. We calculate the distance between1
(the smallest element of this array) and the current largestmx
, which is5
. The distance isabs(1 - 5) = 4
. Then, we calculate the distance between9
(the largest element of this array) and the current smallestmi
, which is1
. The distance here isabs(9 - 1) = 8
. We updateans
to the maximum ofans
and these new distances.ans
is now updated to8
, which is the maximum distance found. We check if we need to updatemi
ormx
. Since1
is equal to currentmi
and9
is greater than currentmx
, we updatemx
to9
.
Finally, after iterating through all arrays, we have the largest distance ans
as 8
, which is the correct maximum distance between two integers from two different arrays. Thus, we return 8
.
Solution Implementation
1from typing import List
2
3class Solution:
4 def maxDistance(self, arrays: List[List[int]]) -> int:
5 # Initialize the maximum distance and the minimum and maximum values
6 max_distance = 0
7 min_value, max_value = arrays[0][0], arrays[0][-1]
8
9 # Iterate over the arrays starting from the second one
10 for array in arrays[1:]:
11 # Compute the potential distances between the current array's first or last element
12 # with the opposite ends of the known range (max_value and min_value)
13 distance_min_to_max = abs(array[0] - max_value)
14 distance_max_to_min = abs(array[-1] - min_value)
15
16 # Update max_distance to be the maximum of the current max_distance and the new distances
17 max_distance = max(max_distance, distance_min_to_max, distance_max_to_min)
18
19 # Update the overall min_value and max_value with the current array's values
20 min_value = min(min_value, array[0])
21 max_value = max(max_value, array[-1])
22
23 # Return the computed maximum distance between any two pairs
24 return max_distance
25
1class Solution {
2
3 // Method to find the maximum distance between any pair of elements
4 // from different arrays within the list of arrays.
5 public int maxDistance(List<List<Integer>> arrays) {
6 // Initializing 'ans' as 0 to hold the maximum distance encountered.
7 int maxDistance = 0;
8
9 // Assign the first element of the first array as the minimum known value 'min'.
10 int min = arrays.get(0).get(0);
11
12 // Assign the last element of the first array as the maximum known value 'max'.
13 int max = arrays.get(0).get(arrays.get(0).size() - 1);
14
15 // Iterate over the remaining arrays in the list starting from the second array.
16 for (int i = 1; i < arrays.size(); ++i) {
17 List<Integer> array = arrays.get(i);
18
19 // Calculate the absolute difference between the first element of the current array
20 // and the known maximum. This represents a potential max distance.
21 int distanceWithMax = Math.abs(array.get(0) - max);
22
23 // Calculate the absolute difference between the last element of the current array
24 // and the known minimum. This represents a potential max distance.
25 int distanceWithMin = Math.abs(array.get(array.size() - 1) - min);
26
27 // Update 'maxDistance' with the greater of the two newly calculated distances
28 // if either is larger than the current 'maxDistance'.
29 maxDistance = Math.max(maxDistance, Math.max(distanceWithMax, distanceWithMin));
30
31 // Update the known minimum value 'min' if the first item of the current array is smaller.
32 min = Math.min(min, array.get(0));
33
34 // Update the known maximum value 'max' if the last item of the current array is larger.
35 max = Math.max(max, array.get(array.size() - 1));
36 }
37
38 // Return the largest distance found.
39 return maxDistance;
40 }
41}
42
1#include <vector>
2#include <algorithm> // include the algorithm header for using min, max functions
3
4class Solution {
5public:
6 int maxDistance(vector<vector<int>>& arrays) {
7 int maxDistance = 0; // maximum distance found so far
8 int minElement = arrays[0][0]; // initialize with the first element of the first array
9 int maxElement = arrays[0].back(); // initialize with the last element of the first array
10
11 // Start from the second array
12 for (int i = 1; i < arrays.size(); ++i) {
13 // Reference to the current array to avoid copying
14 auto& currentArray = arrays[i];
15
16 // Calculate distance between the smallest element so far and the last element of the current array
17 int distanceToMin = abs(currentArray[0] - maxElement);
18
19 // Calculate distance between the largest element so far and the first element of the current array
20 int distanceToMax = abs(currentArray.back() - minElement);
21
22 // Update maxDistance with the largest of the three: itself, distanceToMin, distanceToMax
23 maxDistance = max({maxDistance, distanceToMin, distanceToMax});
24
25 // Update minElement with the smaller between minElement and the first element of the current array
26 minElement = min(minElement, currentArray[0]);
27
28 // Update maxElement with the larger between maxElement and the last element of the current array
29 maxElement = max(maxElement, currentArray.back());
30 }
31
32 // Return the maximum distance found
33 return maxDistance;
34 }
35};
36
1// Importing the first and last functions from lodash for array manipulation
2import { first, last } from 'lodash';
3
4// Function to calculate the maximum distance between any pair of elements from different arrays
5function maxDistance(arrays: number[][]): number {
6 // Maximum distance found so far
7 let maxDistance = 0;
8 // Initialize with the first element of the first sub-array
9 let minElement = first(arrays[0]) as number;
10 // Initialize with the last element of the first sub-array
11 let maxElement = last(arrays[0]) as number;
12
13 // Start from the second sub-array
14 for (let i = 1; i < arrays.length; ++i) {
15 // Reference to the current sub-array to avoid copying
16 const currentArray = arrays[i];
17
18 // Calculate distance between the smallest element so far and the last element of the current sub-array
19 const distanceToMin = Math.abs(first(currentArray) as number - maxElement);
20
21 // Calculate distance between the largest element so far and the first element of the current sub-array
22 const distanceToMax = Math.abs(last(currentArray) as number - minElement);
23
24 // Update maxDistance with the largest of the three: itself, distanceToMin, distanceToMax
25 maxDistance = Math.max(maxDistance, distanceToMin, distanceToMax);
26
27 // Update minElement with the smaller between minElement and the first element of the current sub-array
28 minElement = Math.min(minElement, first(currentArray) as number);
29
30 // Update maxElement with the larger between maxElement and the last element of the current sub-array
31 maxElement = Math.max(maxElement, last(currentArray) as number);
32 }
33
34 // Return the maximum distance found
35 return maxDistance;
36}
37
Time and Space Complexity
Time Complexity
The time complexity of the given code is primarily determined by the loop that iterates over all elements of the arrays
list, except the first element. In the worst case, where there are n
arrays inside the arrays
list, we iterate n - 1
times. Inside the loop, we execute a constant number of operations for each array: calculating the absolute difference between the first and last elements with mi
and mx
, updating ans
, and updating mi
and mx
with the current array's first and last elements, respectively. Since all these operations inside the loop have a constant time complexity, the overall time complexity of the loop is O(n)
.
Hence, the total time complexity of the code is O(n)
.
Space Complexity
The space complexity is determined by the additional memory used by the program which is not part of the input. In the given code, we use a fixed number of variables (ans
, mi
, mx
, a
, b
) that do not depend on the size of the input. No other dynamic data structures or recursive calls which could use additional space are involved. Therefore, the space complexity is O(1)
, which represents constant space usage.
Learn more about how to find time and space complexity quickly using problem constraints.
Is the following code DFS or BFS?
void search(Node root) { if (!root) return; visit(root); root.visited = true; for (Node node in root.adjacent) { if (!node.visited) { search(node); } } }
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
LeetCode 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 we
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 algomonster s3 us east 2 amazonaws com recursion jpg You first
Want a Structured Path to Master System Design Too? Don’t Miss This!