Skip to content

Commit 071f1b0

Browse files
authored
feat: add solutions to lc problem: No.2040 (#3098)
No.2040.Kth Smallest Product of Two Sorted Arrays
1 parent 66b4da5 commit 071f1b0

File tree

9 files changed

+573
-28
lines changed

9 files changed

+573
-28
lines changed

solution/2000-2099/2037.Minimum Number of Moves to Seat Everyone/README.md

+1-6
Original file line numberDiff line numberDiff line change
@@ -163,12 +163,7 @@ func abs(x int) int {
163163
function minMovesToSeat(seats: number[], students: number[]): number {
164164
seats.sort((a, b) => a - b);
165165
students.sort((a, b) => a - b);
166-
const n = seats.length;
167-
let ans = 0;
168-
for (let i = 0; i < n; i++) {
169-
ans += Math.abs(seats[i] - students[i]);
170-
}
171-
return ans;
166+
return seats.reduce((acc, seat, i) => acc + Math.abs(seat - students[i]), 0);
172167
}
173168
```
174169

solution/2000-2099/2037.Minimum Number of Moves to Seat Everyone/README_EN.md

+1-6
Original file line numberDiff line numberDiff line change
@@ -165,12 +165,7 @@ func abs(x int) int {
165165
function minMovesToSeat(seats: number[], students: number[]): number {
166166
seats.sort((a, b) => a - b);
167167
students.sort((a, b) => a - b);
168-
const n = seats.length;
169-
let ans = 0;
170-
for (let i = 0; i < n; i++) {
171-
ans += Math.abs(seats[i] - students[i]);
172-
}
173-
return ans;
168+
return seats.reduce((acc, seat, i) => acc + Math.abs(seat - students[i]), 0);
174169
}
175170
```
176171

Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
11
function minMovesToSeat(seats: number[], students: number[]): number {
22
seats.sort((a, b) => a - b);
33
students.sort((a, b) => a - b);
4-
const n = seats.length;
5-
let ans = 0;
6-
for (let i = 0; i < n; i++) {
7-
ans += Math.abs(seats[i] - students[i]);
8-
}
9-
return ans;
4+
return seats.reduce((acc, seat, i) => acc + Math.abs(seat - students[i]), 0);
105
}

solution/2000-2099/2040.Kth Smallest Product of Two Sorted Arrays/README.md

+195-5
Original file line numberDiff line numberDiff line change
@@ -75,32 +75,222 @@ tags:
7575

7676
<!-- solution:start -->
7777

78-
### 方法一
78+
### 方法一:二分查找
79+
80+
我们可以二分枚举乘积的值 $p$,定义二分的区间为 $[l, r]$,其中 $l = -\text{max}(|\text{nums1}[0]|, |\text{nums1}[n - 1]|) \times \text{max}(|\text{nums2}[0]|, |\text{nums2}[n - 1]|)$, $r = -l$。
81+
82+
对于每个 $p$,我们计算出乘积小于等于 $p$ 的乘积的个数,如果这个个数大于等于 $k$,那么说明第 $k$ 小的乘积一定小于等于 $p$,我们就可以将区间右端点缩小到 $p$,否则我们将区间左端点增大到 $p + 1$。
83+
84+
那么问题的关键就是如何计算乘积小于等于 $p$ 的乘积的个数。我们可以枚举 $\text{nums1}$ 中的每个数 $x$,分类讨论:
85+
86+
- 如果 $x > 0$,那么 $x \times \text{nums2}[i]$ 随着 $i$ 的增大是单调递增的,我们可以使用二分查找找到最小的 $i$,使得 $x \times \text{nums2}[i] > p$,那么 $i$ 就是小于等于 $p$ 的乘积的个数,累加到个数 $\text{cnt}$ 中;
87+
- 如果 $x < 0$,那么 $x \times \text{nums2}[i]$ 随着 $i$ 的增大是单调递减的,我们可以使用二分查找找到最小的 $i$,使得 $x \times \text{nums2}[i] \leq p$,那么 $n - i$ 就是小于等于 $p$ 的乘积的个数,累加到个数 $\text{cnt}$ 中;
88+
- 如果 $x = 0$,那么 $x \times \text{nums2}[i] = 0$,如果 $p \geq 0$,那么 $n$ 就是小于等于 $p$ 的乘积的个数,累加到个数 $\text{cnt}$ 中。
89+
90+
这样我们就可以通过二分查找找到第 $k$ 小的乘积。
91+
92+
时间复杂度 $O(m \times \log n \times \log M)$,其中 $m$ 和 $n$ 分别为 $\text{nums1}$ 和 $\text{nums2}$ 的长度,而 $M$ 为 $\text{nums1}$ 和 $\text{nums2}$ 中的最大值的绝对值。
7993

8094
<!-- tabs:start -->
8195

8296
#### Python3
8397

8498
```python
85-
99+
class Solution:
100+
def kthSmallestProduct(self, nums1: List[int], nums2: List[int], k: int) -> int:
101+
def count(p: int) -> int:
102+
cnt = 0
103+
n = len(nums2)
104+
for x in nums1:
105+
if x > 0:
106+
cnt += bisect_right(nums2, p / x)
107+
elif x < 0:
108+
cnt += n - bisect_left(nums2, p / x)
109+
else:
110+
cnt += n * int(p >= 0)
111+
return cnt
112+
113+
mx = max(abs(nums1[0]), abs(nums1[-1])) * max(abs(nums2[0]), abs(nums2[-1]))
114+
return bisect_left(range(-mx, mx + 1), k, key=count) - mx
86115
```
87116

88117
#### Java
89118

90119
```java
91-
120+
class Solution {
121+
private int[] nums1;
122+
private int[] nums2;
123+
124+
public long kthSmallestProduct(int[] nums1, int[] nums2, long k) {
125+
this.nums1 = nums1;
126+
this.nums2 = nums2;
127+
int m = nums1.length;
128+
int n = nums2.length;
129+
int a = Math.max(Math.abs(nums1[0]), Math.abs(nums1[m - 1]));
130+
int b = Math.max(Math.abs(nums2[0]), Math.abs(nums2[n - 1]));
131+
long r = (long) a * b;
132+
long l = (long) -a * b;
133+
while (l < r) {
134+
long mid = (l + r) >> 1;
135+
if (count(mid) >= k) {
136+
r = mid;
137+
} else {
138+
l = mid + 1;
139+
}
140+
}
141+
return l;
142+
}
143+
144+
private long count(long p) {
145+
long cnt = 0;
146+
int n = nums2.length;
147+
for (int x : nums1) {
148+
if (x > 0) {
149+
int l = 0, r = n;
150+
while (l < r) {
151+
int mid = (l + r) >> 1;
152+
if ((long) x * nums2[mid] > p) {
153+
r = mid;
154+
} else {
155+
l = mid + 1;
156+
}
157+
}
158+
cnt += l;
159+
} else if (x < 0) {
160+
int l = 0, r = n;
161+
while (l < r) {
162+
int mid = (l + r) >> 1;
163+
if ((long) x * nums2[mid] <= p) {
164+
r = mid;
165+
} else {
166+
l = mid + 1;
167+
}
168+
}
169+
cnt += n - l;
170+
} else if (p >= 0) {
171+
cnt += n;
172+
}
173+
}
174+
return cnt;
175+
}
176+
}
92177
```
93178

94179
#### C++
95180

96181
```cpp
97-
182+
class Solution {
183+
public:
184+
long long kthSmallestProduct(vector<int>& nums1, vector<int>& nums2, long long k) {
185+
int m = nums1.size(), n = nums2.size();
186+
int a = max(abs(nums1[0]), abs(nums1[m - 1]));
187+
int b = max(abs(nums2[0]), abs(nums2[n - 1]));
188+
long long r = 1LL * a * b;
189+
long long l = -r;
190+
auto count = [&](long long p) {
191+
long long cnt = 0;
192+
for (int x : nums1) {
193+
if (x > 0) {
194+
int l = 0, r = n;
195+
while (l < r) {
196+
int mid = (l + r) >> 1;
197+
if (1LL * x * nums2[mid] > p) {
198+
r = mid;
199+
} else {
200+
l = mid + 1;
201+
}
202+
}
203+
cnt += l;
204+
} else if (x < 0) {
205+
int l = 0, r = n;
206+
while (l < r) {
207+
int mid = (l + r) >> 1;
208+
if (1LL * x * nums2[mid] <= p) {
209+
r = mid;
210+
} else {
211+
l = mid + 1;
212+
}
213+
}
214+
cnt += n - l;
215+
} else if (p >= 0) {
216+
cnt += n;
217+
}
218+
}
219+
return cnt;
220+
};
221+
while (l < r) {
222+
long long mid = (l + r) >> 1;
223+
if (count(mid) >= k) {
224+
r = mid;
225+
} else {
226+
l = mid + 1;
227+
}
228+
}
229+
return l;
230+
}
231+
};
98232
```
99233
100234
#### Go
101235
102236
```go
103-
237+
func kthSmallestProduct(nums1 []int, nums2 []int, k int64) int64 {
238+
m := len(nums1)
239+
n := len(nums2)
240+
a := max(abs(nums1[0]), abs(nums1[m-1]))
241+
b := max(abs(nums2[0]), abs(nums2[n-1]))
242+
r := int64(a) * int64(b)
243+
l := -r
244+
245+
count := func(p int64) int64 {
246+
var cnt int64
247+
for _, x := range nums1 {
248+
if x > 0 {
249+
l, r := 0, n
250+
for l < r {
251+
mid := (l + r) >> 1
252+
if int64(x)*int64(nums2[mid]) > p {
253+
r = mid
254+
} else {
255+
l = mid + 1
256+
}
257+
}
258+
cnt += int64(l)
259+
} else if x < 0 {
260+
l, r := 0, n
261+
for l < r {
262+
mid := (l + r) >> 1
263+
if int64(x)*int64(nums2[mid]) <= p {
264+
r = mid
265+
} else {
266+
l = mid + 1
267+
}
268+
}
269+
cnt += int64(n - l)
270+
} else if p >= 0 {
271+
cnt += int64(n)
272+
}
273+
}
274+
return cnt
275+
}
276+
277+
for l < r {
278+
mid := (l + r) >> 1
279+
if count(mid) >= k {
280+
r = mid
281+
} else {
282+
l = mid + 1
283+
}
284+
}
285+
return l
286+
}
287+
288+
func abs(x int) int {
289+
if x < 0 {
290+
return -x
291+
}
292+
return x
293+
}
104294
```
105295

106296
<!-- tabs:end -->

0 commit comments

Comments
 (0)