diff --git a/lcci/16.06.Smallest Difference/README.md b/lcci/16.06.Smallest Difference/README.md index 1b693a7efb1b5..818e152511860 100644 --- a/lcci/16.06.Smallest Difference/README.md +++ b/lcci/16.06.Smallest Difference/README.md @@ -5,6 +5,7 @@ ## 题目描述 +
给定两个整数数组a
和b
,计算具有最小差绝对值的一对数值(每个数组中取一个值),并返回该对数值的差
示例:
输入:{1, 3, 15, 11, 2}, {23, 127, 235, 19, 8} @@ -21,54 +22,133 @@ +**方法一:排序 + 二分查找** + +我们可以对数组 $b$ 进行排序,并对数组 $a$ 中的每个元素 $x$ 在数组 $b$ 中进行二分查找,找到最接近 $x$ 的元素 $y$,那么 $x$ 和 $y$ 的差的绝对值就是 $x$ 和 $b$ 中最接近 $x$ 的元素的差的绝对值。 + +时间复杂度 $O(n \times \log n)$,空间复杂度 $O(\log n)$。其中 $n$ 是数组 $b$ 的长度。 + +**方法二:排序 + 双指针** + +我们可以对数组 $a$ 和 $b$ 分别进行排序,然后使用双指针的方法,维护两个指针 $i$ 和 $j$,初始时分别指向数组 $a$ 和 $b$ 的起始位置。每一次,我们计算 $a[i]$ 和 $b[j]$ 的差的绝对值,并且更新答案。如果 $a[i]$ 和 $b[j]$ 指向的两个元素中的一个元素比另一个元素要小,则将指向较小元素的指针向前移动一步。当至少有一个指针超出数组范围时,遍历结束。 + +时间复杂度 $O(n \times \log n)$,空间复杂度 $O(\log n)$。其中 $n$ 是数组 $a$ 和 $b$ 的长度。 + ### **Python3** +```python +class Solution: + def smallestDifference(self, a: List[int], b: List[int]) -> int: + b.sort() + ans = inf + n = len(b) + for x in a: + j = bisect_left(b, x) + if j < n: + ans = min(ans, b[j] - x) + if j: + ans = min(ans, x - b[j - 1]) + return ans +``` + ```python class Solution: def smallestDifference(self, a: List[int], b: List[int]) -> int: a.sort() b.sort() i = j = 0 - res = inf + ans = inf while i < len(a) and j < len(b): - res = min(res, abs(a[i] - b[j])) - if a[i] > b[j]: - j += 1 - else: + ans = min(ans, abs(a[i] - b[j])) + if a[i] < b[j]: i += 1 - return res + else: + j += 1 + return ans ``` ### **Java** +```java +class Solution { + public int smallestDifference(int[] a, int[] b) { + Arrays.sort(b); + long ans = Long.MAX_VALUE; + for (int x : a) { + int j = search(b, x); + if (j < b.length) { + ans = Math.min(ans, (long) b[j] - x); + } + if (j > 0) { + ans = Math.min(ans, (long) x - b[j - 1]); + } + } + return (int) ans; + } + + private int search(int[] nums, int x) { + int l = 0, r = nums.length; + while (l < r) { + int mid = (l + r) >> 1; + if (nums[mid] >= x) { + r = mid; + } else { + l = mid + 1; + } + } + return l; + } +} +``` + ```java class Solution { public int smallestDifference(int[] a, int[] b) { Arrays.sort(a); Arrays.sort(b); int i = 0, j = 0; - long res = Long.MAX_VALUE; + long ans = Long.MAX_VALUE; while (i < a.length && j < b.length) { - res = Math.min(res, Math.abs((long) a[i] - (long) b[j])); - if (a[i] > b[j]) { - ++j; - } else { + ans = Math.min(ans, Math.abs((long) a[i] - (long) b[j])); + if (a[i] < b[j]) { ++i; + } else { + ++j; } } - return (int) res; + return (int) ans; } } ``` ### **C++** +```cpp +class Solution { +public: + int smallestDifference(vector& a, vector & b) { + sort(b.begin(), b.end()); + long long ans = LONG_LONG_MAX; + for (int x : a) { + auto it = lower_bound(b.begin(), b.end(), x); + if (it != b.end()) { + ans = min(ans, (long long) *it - x); + } + if (it != b.begin()) { + ans = min(ans, x - (long long) *prev(it)); + } + } + return ans; + } +}; +``` + ```cpp class Solution { public: @@ -76,35 +156,61 @@ public: sort(a.begin(), a.end()); sort(b.begin(), b.end()); int i = 0, j = 0; - long res = LONG_MAX; + long long ans = LONG_LONG_MAX; while (i < a.size() && j < b.size()) { - res = min(res, abs((long) a[i] - (long) b[j])); - if (a[i] > b[j]) - ++j; - else + ans = min(ans, abs(1LL * a[i] - 1LL * b[j])); + if (a[i] < b[j]) { ++i; + } else { + ++j; + } } - return res; + return ans; } }; ``` ### **Go** +```go +func smallestDifference(a []int, b []int) int { + sort.Ints(b) + var ans int = 1e18 + for _, x := range a { + i := sort.SearchInts(b, x) + if i < len(b) { + ans = min(ans, b[i]-x) + } + if i > 0 { + ans = min(ans, x-b[i-1]) + } + } + return ans +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} +``` + ```go func smallestDifference(a []int, b []int) int { sort.Ints(a) sort.Ints(b) - i, j, res := 0, 0, 2147483647 + i, j := 0, 0 + var ans int = 1e18 for i < len(a) && j < len(b) { - res = min(res, abs(a[i]-b[j])) - if a[i] > b[j] { - j++ - } else { + ans = min(ans, abs(a[i]-b[j])) + if a[i] < b[j] { i++ + } else { + j++ } } - return res + return ans } func abs(a int) int { @@ -122,6 +228,55 @@ func min(a, b int) int { } ``` +### **TypeScript** + +```ts +function smallestDifference(a: number[], b: number[]): number { + b.sort((a, b) => a - b); + let ans = Infinity; + const search = (nums: number[], x: number): number => { + let [l, r] = [0, nums.length]; + while (l < r) { + const mid = (l + r) >> 1; + if (nums[mid] >= x) { + r = mid; + } else { + l = mid + 1; + } + } + return l; + }; + for (const x of a) { + const j = search(b, x); + if (j < b.length) { + ans = Math.min(ans, b[j] - x); + } + if (j > 0) { + ans = Math.min(ans, x - b[j - 1]); + } + } + return ans; +} +``` + +```ts +function smallestDifference(a: number[], b: number[]): number { + a.sort((a, b) => a - b); + b.sort((a, b) => a - b); + let [i, j] = [0, 0]; + let ans = Infinity; + while (i < a.length && j < b.length) { + ans = Math.min(ans, Math.abs(a[i] - b[j])); + if (a[i] < b[j]) { + ++i; + } else { + ++j; + } + } + return ans; +} +``` + ### **...** ``` diff --git a/lcci/16.06.Smallest Difference/README_EN.md b/lcci/16.06.Smallest Difference/README_EN.md index 516d80d47055c..3b80a516eebfb 100644 --- a/lcci/16.06.Smallest Difference/README_EN.md +++ b/lcci/16.06.Smallest Difference/README_EN.md @@ -26,6 +26,18 @@ ## Solutions +**Solution 1: Sorting + Binary Search** + +We can sort the array $b$, and for each element $x$ in array $a$, perform a binary search in array $b$ to find the element $y$ closest to $x$. Then, the absolute difference between $x$ and $y$ is the absolute difference between $x$ and the closest element in $b$. + +The time complexity is $O(n \times \log n)$, and the space complexity is $O(\log n)$. Here, $n$ is the length of array $b$. + +**Solution 2: Sorting + Two Pointers** + +We can sort both arrays $a$ and $b$, and use two pointers $i$ and $j$ to maintain the current positions in the two arrays. Initially, $i$ and $j$ point to the beginning of arrays $a$ and $b$, respectively. At each step, we calculate the absolute difference between $a[i]$ and $b[j]$, and update the answer. If one of the elements pointed to by $i$ and $j$ is smaller than the other, we move the pointer pointing to the smaller element forward by one step. The traversal ends when at least one of the pointers goes beyond the array range. + +The time complexity is $O(n \times \log n)$, and the space complexity is $O(\log n)$. Here, $n$ is the length of arrays $a$ and $b$. + ### **Python3** @@ -35,41 +47,108 @@ class Solution: def smallestDifference(self, a: List[int], b: List[int]) -> int: a.sort() b.sort() - i = j = 0 - res = inf - while i < len(a) and j < len(b): - res = min(res, abs(a[i] - b[j])) - if a[i] > b[j]: - j += 1 - else: - i += 1 - return res + ans = inf + n = len(b) + for x in a: + j = bisect_left(b, x) + if j < n: + ans = min(ans, b[j] - x) + if j: + ans = min(ans, x - b[j - 1]) + return ans +``` + +```python +class Solution: + def smallestDifference(self, a: List[int], b: List[int]) -> int: + b.sort() + ans = inf + n = len(b) + for x in a: + j = bisect_left(b, x) + if j < n: + ans = min(ans, b[j] - x) + if j: + ans = min(ans, x - b[j - 1]) + return ans ``` ### **Java** +```java +class Solution { + public int smallestDifference(int[] a, int[] b) { + Arrays.sort(b); + long ans = Long.MAX_VALUE; + for (int x : a) { + int j = search(b, x); + if (j < b.length) { + ans = Math.min(ans, (long) b[j] - x); + } + if (j > 0) { + ans = Math.min(ans, (long) x - b[j - 1]); + } + } + return (int) ans; + } + + private int search(int[] nums, int x) { + int l = 0, r = nums.length; + while (l < r) { + int mid = (l + r) >> 1; + if (nums[mid] >= x) { + r = mid; + } else { + l = mid + 1; + } + } + return l; + } +} +``` + ```java class Solution { public int smallestDifference(int[] a, int[] b) { Arrays.sort(a); Arrays.sort(b); int i = 0, j = 0; - long res = Long.MAX_VALUE; + long ans = Long.MAX_VALUE; while (i < a.length && j < b.length) { - res = Math.min(res, Math.abs((long) a[i] - (long) b[j])); - if (a[i] > b[j]) { - ++j; - } else { + ans = Math.min(ans, Math.abs((long) a[i] - (long) b[j])); + if (a[i] < b[j]) { ++i; + } else { + ++j; } } - return (int) res; + return (int) ans; } } ``` ### **C++** +```cpp +class Solution { +public: + int smallestDifference(vector & a, vector & b) { + sort(b.begin(), b.end()); + long long ans = LONG_LONG_MAX; + for (int x : a) { + auto it = lower_bound(b.begin(), b.end(), x); + if (it != b.end()) { + ans = min(ans, (long long) *it - x); + } + if (it != b.begin()) { + ans = min(ans, x - (long long) *prev(it)); + } + } + return ans; + } +}; +``` + ```cpp class Solution { public: @@ -77,35 +156,61 @@ public: sort(a.begin(), a.end()); sort(b.begin(), b.end()); int i = 0, j = 0; - long res = LONG_MAX; + long long ans = LONG_LONG_MAX; while (i < a.size() && j < b.size()) { - res = min(res, abs((long) a[i] - (long) b[j])); - if (a[i] > b[j]) - ++j; - else + ans = min(ans, abs(1LL * a[i] - 1LL * b[j])); + if (a[i] < b[j]) { ++i; + } else { + ++j; + } } - return res; + return ans; } }; ``` ### **Go** +```go +func smallestDifference(a []int, b []int) int { + sort.Ints(b) + var ans int = 1e18 + for _, x := range a { + i := sort.SearchInts(b, x) + if i < len(b) { + ans = min(ans, b[i]-x) + } + if i > 0 { + ans = min(ans, x-b[i-1]) + } + } + return ans +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} +``` + ```go func smallestDifference(a []int, b []int) int { sort.Ints(a) sort.Ints(b) - i, j, res := 0, 0, 2147483647 + i, j := 0, 0 + var ans int = 1e18 for i < len(a) && j < len(b) { - res = min(res, abs(a[i]-b[j])) - if a[i] > b[j] { - j++ - } else { + ans = min(ans, abs(a[i]-b[j])) + if a[i] < b[j] { i++ + } else { + j++ } } - return res + return ans } func abs(a int) int { @@ -123,6 +228,55 @@ func min(a, b int) int { } ``` +### **TypeScript** + +```ts +function smallestDifference(a: number[], b: number[]): number { + b.sort((a, b) => a - b); + let ans = Infinity; + const search = (nums: number[], x: number): number => { + let [l, r] = [0, nums.length]; + while (l < r) { + const mid = (l + r) >> 1; + if (nums[mid] >= x) { + r = mid; + } else { + l = mid + 1; + } + } + return l; + }; + for (const x of a) { + const j = search(b, x); + if (j < b.length) { + ans = Math.min(ans, b[j] - x); + } + if (j > 0) { + ans = Math.min(ans, x - b[j - 1]); + } + } + return ans; +} +``` + +```ts +function smallestDifference(a: number[], b: number[]): number { + a.sort((a, b) => a - b); + b.sort((a, b) => a - b); + let [i, j] = [0, 0]; + let ans = Infinity; + while (i < a.length && j < b.length) { + ans = Math.min(ans, Math.abs(a[i] - b[j])); + if (a[i] < b[j]) { + ++i; + } else { + ++j; + } + } + return ans; +} +``` + ### **...** ``` diff --git a/lcci/16.06.Smallest Difference/Solution.cpp b/lcci/16.06.Smallest Difference/Solution.cpp index c7e67031dcedd..20da03808fc15 100644 --- a/lcci/16.06.Smallest Difference/Solution.cpp +++ b/lcci/16.06.Smallest Difference/Solution.cpp @@ -1,17 +1,18 @@ -class Solution { -public: - int smallestDifference(vector & a, vector & b) { - sort(a.begin(), a.end()); - sort(b.begin(), b.end()); - int i = 0, j = 0; - long res = LONG_MAX; - while (i < a.size() && j < b.size()) { - res = min(res, abs((long) a[i] - (long) b[j])); - if (a[i] > b[j]) - ++j; - else - ++i; - } - return res; - } +class Solution { +public: + int smallestDifference(vector & a, vector & b) { + sort(a.begin(), a.end()); + sort(b.begin(), b.end()); + int i = 0, j = 0; + long long ans = LONG_LONG_MAX; + while (i < a.size() && j < b.size()) { + ans = min(ans, abs(1LL * a[i] - 1LL * b[j])); + if (a[i] < b[j]) { + ++i; + } else { + ++j; + } + } + return ans; + } }; \ No newline at end of file diff --git a/lcci/16.06.Smallest Difference/Solution.go b/lcci/16.06.Smallest Difference/Solution.go index 9cf5ef77881ff..f3b801ae50b78 100644 --- a/lcci/16.06.Smallest Difference/Solution.go +++ b/lcci/16.06.Smallest Difference/Solution.go @@ -1,16 +1,17 @@ func smallestDifference(a []int, b []int) int { sort.Ints(a) sort.Ints(b) - i, j, res := 0, 0, 2147483647 + i, j := 0, 0 + var ans int = 1e18 for i < len(a) && j < len(b) { - res = min(res, abs(a[i]-b[j])) - if a[i] > b[j] { - j++ - } else { + ans = min(ans, abs(a[i]-b[j])) + if a[i] < b[j] { i++ + } else { + j++ } } - return res + return ans } func abs(a int) int { diff --git a/lcci/16.06.Smallest Difference/Solution.java b/lcci/16.06.Smallest Difference/Solution.java index 56438d97705fa..d52ce57673417 100644 --- a/lcci/16.06.Smallest Difference/Solution.java +++ b/lcci/16.06.Smallest Difference/Solution.java @@ -1,17 +1,17 @@ -class Solution { - public int smallestDifference(int[] a, int[] b) { - Arrays.sort(a); - Arrays.sort(b); - int i = 0, j = 0; - long res = Long.MAX_VALUE; - while (i < a.length && j < b.length) { - res = Math.min(res, Math.abs((long) a[i] - (long) b[j])); - if (a[i] > b[j]) { - ++j; - } else { - ++i; - } - } - return (int) res; - } +class Solution { + public int smallestDifference(int[] a, int[] b) { + Arrays.sort(a); + Arrays.sort(b); + int i = 0, j = 0; + long ans = Long.MAX_VALUE; + while (i < a.length && j < b.length) { + ans = Math.min(ans, Math.abs((long) a[i] - (long) b[j])); + if (a[i] < b[j]) { + ++i; + } else { + ++j; + } + } + return (int) ans; + } } \ No newline at end of file diff --git a/lcci/16.06.Smallest Difference/Solution.py b/lcci/16.06.Smallest Difference/Solution.py index e133c1c881c0e..af716e9044e3c 100644 --- a/lcci/16.06.Smallest Difference/Solution.py +++ b/lcci/16.06.Smallest Difference/Solution.py @@ -1,13 +1,13 @@ -class Solution: - def smallestDifference(self, a: List[int], b: List[int]) -> int: - a.sort() - b.sort() - i = j = 0 - res = inf - while i < len(a) and j < len(b): - res = min(res, abs(a[i] - b[j])) - if a[i] > b[j]: - j += 1 - else: - i += 1 - return res +class Solution: + def smallestDifference(self, a: List[int], b: List[int]) -> int: + a.sort() + b.sort() + i = j = 0 + ans = inf + while i < len(a) and j < len(b): + ans = min(ans, abs(a[i] - b[j])) + if a[i] < b[j]: + i += 1 + else: + j += 1 + return ans diff --git a/lcci/16.06.Smallest Difference/Solution.ts b/lcci/16.06.Smallest Difference/Solution.ts new file mode 100644 index 0000000000000..8f848fcff7f39 --- /dev/null +++ b/lcci/16.06.Smallest Difference/Solution.ts @@ -0,0 +1,15 @@ +function smallestDifference(a: number[], b: number[]): number { + a.sort((a, b) => a - b); + b.sort((a, b) => a - b); + let [i, j] = [0, 0]; + let ans = Infinity; + while (i < a.length && j < b.length) { + ans = Math.min(ans, Math.abs(a[i] - b[j])); + if (a[i] < b[j]) { + ++i; + } else { + ++j; + } + } + return ans; +}