Find Nearest Point That Has the Same X or Y Coordinate
EasyPrompt
You are given two integers, x and y, which represent your current location on a Cartesian grid: (x, y). You are also given an array points where each points[i] = [ai, bi] represents that a point exists at (ai, bi). A point is valid if it shares the same x-coordinate or the same y-coordinate as your location.
Return the index (0-indexed) of the valid point with the smallest Manhattan distance from your current location. If there are multiple, return the valid point with the smallest index. If there are no valid points, return -1.
The Manhattan distance between two points (x1, y1) and (x2, y2) is abs(x1 - x2) + abs(y1 - y2).
Example 1:
Input: x = 3, y = 4, points = [[1,2],[3,1],[2,4],[2,3],[4,4]]
Output: 2
Explanation: Of all the points, only [3,1], [2,4] and [4,4] are valid. Of the valid points, [2,4] and [4,4] have the smallest Manhattan distance from your current location, with a distance of 1. [2,4] has the smallest index, so return 2.Example 2:
Input: x = 3, y = 4, points = [[3,4]]
Output: 0
Explanation: The answer is allowed to be on the same location as your current location.Example 3:
Input: x = 3, y = 4, points = [[2,3]]
Output: -1
Explanation: There are no valid points.
Constraints:
1 <= points.length <= 104points[i].length == 21 <= x, y, ai, bi <= 104
Approaches
2 approaches with complexity analysis and trade-offs.
This approach separates the problem into two distinct steps. First, it filters the original list of points to create a new list containing only the valid points (those sharing an x or y coordinate). Second, it iterates through this new list of valid points to find the one with the smallest Manhattan distance. This method is straightforward but less optimal due to its use of extra memory and two separate loops.
Algorithm
- Initialize two empty lists, one for valid points (
validPoints) and one for their original indices (validIndices). - Iterate through the input
pointsarray with indexi. - For each point
p, check if its x-coordinate matchesxor its y-coordinate matchesy. - If the point is valid, add the point to
validPointsand its indexitovalidIndices. - After the first loop, if
validPointsis empty, return -1. - Initialize
minDistancetoInteger.MAX_VALUEandresultIndexto -1. - Iterate through the
validPointslist. - For each valid point, calculate its Manhattan distance to
(x, y). - If the calculated distance is less than
minDistance, updateminDistanceto the new distance andresultIndexto the corresponding original index fromvalidIndices. - Return
resultIndex.
Walkthrough
In this method, we first iterate through the entire points array to identify all points that are "valid". A point (a, b) is valid if a == x or b == y. We store these valid points and their original indices in separate auxiliary lists.
After populating our lists of valid points and indices, we check if any were found. If not, we return -1. Otherwise, we proceed to a second loop. This loop iterates through our newly created list of valid points. For each valid point, we calculate its Manhattan distance from the reference point (x, y). We keep track of the minimum distance found so far and the original index of the point that yielded this distance. If we find a point with a distance smaller than our current minimum, we update the minimum distance and the result index. Because we process the valid points in the order of their original indices, this naturally handles the tie-breaking rule (smallest index wins).
import java.util.ArrayList;import java.util.List; class Solution { public int nearestValidPoint(int x, int y, int[][] points) { List<int[]> validPoints = new ArrayList<>(); List<Integer> validIndices = new ArrayList<>(); // First pass: Filter for valid points for (int i = 0; i < points.length; i++) { if (points[i][0] == x || points[i][1] == y) { validPoints.add(points[i]); validIndices.add(i); } } if (validPoints.isEmpty()) { return -1; } int minDistance = Integer.MAX_VALUE; int resultIndex = -1; // Second pass: Find the nearest among valid points for (int i = 0; i < validPoints.size(); i++) { int[] point = validPoints.get(i); int distance = Math.abs(x - point[0]) + Math.abs(y - point[1]); if (distance < minDistance) { minDistance = distance; resultIndex = validIndices.get(i); } } return resultIndex; }}Complexity
Time
O(N), where N is the number of points. The first loop runs N times, and the second loop runs V times (where V ≤ N). The total time complexity is O(N + V), which simplifies to O(N).
Space
O(V), where V is the number of valid points. In the worst-case scenario where all points are valid, the space complexity becomes O(N) to store the valid points and their indices.
Trade-offs
Pros
The logic is separated into clear, distinct steps: filtering and then processing.
It can be easier to reason about for beginners.
Cons
Uses extra space proportional to the number of valid points, which can be up to O(N) in the worst case.
Requires two passes over the data (one on the original array, one on the list of valid points), making it less efficient than a single-pass solution.
This is the most efficient approach, solving the problem in a single pass through the data. It iterates through the points array just once. In each iteration, it checks if the point is valid and, if so, calculates its distance. It maintains a record of the minimum distance found so far and the index of the corresponding point, updating them whenever a closer valid point is found. This avoids the need for extra storage and a second pass.
Algorithm
- Initialize
minDistanceto a very large value (e.g.,Integer.MAX_VALUE). - Initialize
minIndexto -1, which will be the default return value if no valid point is found. - Iterate through the
pointsarray with an indexifrom 0 ton-1. - For each point
p = (px, py):- Check if the point is valid:
if (px == x || py == y). - If it is valid, calculate its Manhattan distance:
distance = abs(x - px) + abs(y - py). - Compare this
distancewithminDistance. Ifdistance < minDistance:- Update
minDistanceto this new, smaller distance. - Update
minIndexto the current indexi.
- Update
- Check if the point is valid:
- After the loop completes, return
minIndex.
Walkthrough
This optimal solution combines the validation, distance calculation, and comparison steps into a single loop. We initialize two variables: minDistance to Integer.MAX_VALUE to track the smallest distance, and minIndex to -1 to store the index of the best point found so far. The -1 initial value for minIndex also handily serves as the return value if no valid points are ever found.
We then iterate through the points array from the first element to the last. For each point, we first check if it shares an x or y coordinate with our location (x, y). If it does, we calculate its Manhattan distance. We then compare this distance with minDistance. If the new distance is strictly smaller, we've found a better candidate point. We update minDistance with this new distance and minIndex with the current point's index.
The strict inequality distance < minDistance is key to handling the tie-breaking rule. If two points have the same minimal distance, the one with the smaller index will be found first. Since we only update when a strictly smaller distance is found, the index of the first-encountered minimal distance point is preserved, satisfying the problem's requirement.
class Solution { public int nearestValidPoint(int x, int y, int[][] points) { int minDistance = Integer.MAX_VALUE; int minIndex = -1; for (int i = 0; i < points.length; i++) { int px = points[i][0]; int py = points[i][1]; // Check if the point is valid if (px == x || py == y) { // Calculate Manhattan distance int distance = Math.abs(x - px) + Math.abs(y - py); // If this point is closer, update the result if (distance < minDistance) { minDistance = distance; minIndex = i; } } } return minIndex; }}Complexity
Time
O(N), where N is the number of points in the input array. We perform a single pass through the array, and each operation inside the loop is constant time.
Space
O(1). We only use a constant amount of extra space for variables like `minDistance` and `minIndex`, regardless of the input size.
Trade-offs
Pros
Extremely efficient, with optimal O(N) time complexity.
Space-efficient, using only O(1) extra space.
Solves the problem in a single, elegant pass.
Implicitly handles the tie-breaking rule (smallest index) due to the single forward pass and strict inequality check.
Cons
There are no significant disadvantages to this approach as it is optimal for the given problem and constraints.
Solutions
Solution
class Solution {public int nearestValidPoint(int x, int y, int[][] points) { int ans = -1, mi = 1000000; for (int i = 0; i < points.length; ++i) { int a = points[i][0], b = points[i][1]; if (a == x || b == y) { int d = Math.abs(a - x) + Math.abs(b - y); if (d < mi) { mi = d; ans = i; } } } return ans; }}class Solution {public: int nearestValidPoint(int x, int y, vector<vector<int>> &points) { int ans = -1, mi = 1e6; for (int i = 0; i < points.size(); ++i) { int a = points[i][0], b = points[i][1]; if (a == x || b == y) { int d = abs(a - x) + abs(b - y); if (d < mi) { mi = d; ans = i; } } } return ans; }};class Solution: def nearestValidPoint(self, x: int, y: int, points: List[List[int]]) -> int: ans, mi = - 1, inf for i, (a, b) in enumerate(points): if a == x or b == y: d = abs(a - x) + abs(b - y) if mi > d: ans, mi = i, d return ansVideo walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.