Find the Distance Value Between Two Arrays
For each element of arr1, binary search arr2 for the nearest neighbor and check the gap.
4 min read
binary-search sorting
Problem#
Given two arrays and integer d, return the count of elements in arr1 for which no element in arr2 lies within distance d.
Examples#
arr1 = [4,5,8], arr2 = [10,9,1,8], d = 2→2arr1 = [1,4,2,3], arr2 = [-4,-3,6,10,20,30], d = 3→2arr1 = [2,1,100,3], arr2 = [-5,-2,10,-3,7], d = 6→1
Constraints#
1 <= arr1.length, arr2.length <= 500,-1000 <= arr1[i], arr2[i] <= 1000,0 <= d <= 100.
Approach#
Sort arr2. For each x in arr1, the only candidates that could be within d are the largest element <= x and the smallest element > x. Use lower_bound to locate both and check.
Solution#
class Solution {public: int findTheDistanceValue(vector<int>& arr1, vector<int>& arr2, int d) { sort(arr2.begin(), arr2.end()); int ans = 0; for (int x : arr1) { auto it = lower_bound(arr2.begin(), arr2.end(), x); bool ok = true; if (it != arr2.end() && abs(*it - x) <= d) ok = false; if (it != arr2.begin() && abs(*prev(it) - x) <= d) ok = false; if (ok) ++ans; } return ans; }};import "sort"
func findTheDistanceValue(arr1 []int, arr2 []int, d int) int { sort.Ints(arr2) abs := func(x int) int { if x < 0 { return -x } return x } ans := 0 for _, x := range arr1 { i := sort.SearchInts(arr2, x) ok := true if i < len(arr2) && abs(arr2[i]-x) <= d { ok = false } if i > 0 && abs(arr2[i-1]-x) <= d { ok = false } if ok { ans++ } } return ans}import bisectfrom typing import List
class Solution: def findTheDistanceValue(self, arr1: List[int], arr2: List[int], d: int) -> int: arr2.sort() ans = 0 for x in arr1: i = bisect.bisect_left(arr2, x) ok = True if i < len(arr2) and abs(arr2[i] - x) <= d: ok = False if i > 0 and abs(arr2[i - 1] - x) <= d: ok = False if ok: ans += 1 return ansvar findTheDistanceValue = function(arr1, arr2, d) { arr2.sort((a, b) => a - b); const lowerBound = (arr, target) => { let lo = 0, hi = arr.length; while (lo < hi) { const mid = (lo + hi) >> 1; if (arr[mid] < target) lo = mid + 1; else hi = mid; } return lo; }; let ans = 0; for (const x of arr1) { const i = lowerBound(arr2, x); let ok = true; if (i < arr2.length && Math.abs(arr2[i] - x) <= d) ok = false; if (i > 0 && Math.abs(arr2[i - 1] - x) <= d) ok = false; if (ok) ans++; } return ans;};class Solution { public int findTheDistanceValue(int[] arr1, int[] arr2, int d) { Arrays.sort(arr2); int ans = 0; for (int x : arr1) { int i = lowerBound(arr2, x); boolean ok = true; if (i < arr2.length && Math.abs(arr2[i] - x) <= d) ok = false; if (i > 0 && Math.abs(arr2[i - 1] - x) <= d) ok = false; if (ok) ans++; } return ans; }
private int lowerBound(int[] arr, int target) { int lo = 0, hi = arr.length; while (lo < hi) { int mid = (lo + hi) >>> 1; if (arr[mid] < target) lo = mid + 1; else hi = mid; } return lo; }}function findTheDistanceValue(arr1: number[], arr2: number[], d: number): number { arr2.sort((a, b) => a - b); const lowerBound = (arr: number[], target: number): number => { let lo = 0, hi = arr.length; while (lo < hi) { const mid = (lo + hi) >> 1; if (arr[mid] < target) lo = mid + 1; else hi = mid; } return lo; }; let ans = 0; for (const x of arr1) { const i = lowerBound(arr2, x); let ok = true; if (i < arr2.length && Math.abs(arr2[i] - x) <= d) ok = false; if (i > 0 && Math.abs(arr2[i - 1] - x) <= d) ok = false; if (ok) ans++; } return ans;}Editorial#
Distance is minimized at the immediate neighbors in sorted order, so we only need two probes per element. Bounds-checking against begin() and end() avoids undefined behavior at the edges.
Complexity#
- Time: O((n + m) log m).
- Space: O(1) extra.
Concept revision#
Related#