Skip to content

Commit a088770

Browse files
committed
feat: add solutions to lc problem: No.1918
No.1918.Kth Smallest Subarray Sum
1 parent e9c26c7 commit a088770

File tree

6 files changed

+369
-2
lines changed

6 files changed

+369
-2
lines changed

solution/1900-1999/1918.Kth Smallest Subarray Sum/README.md

Lines changed: 138 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,22 +61,159 @@
6161

6262
<!-- 这里可写通用的实现逻辑 -->
6363

64+
**方法一:二分查找 + 双指针**
65+
66+
我们注意到,题目中数组元素均为正整数,子数组的和 $s$ 越大,那么数组中子数组和小于等于 $s$ 的个数就越多。这存在一个单调性,因此我们可以考虑使用使用二分查找的方法来求解。
67+
68+
我们二分枚举子数组的和,初始化左右边界分别为数组 $nums$ 中的最小值以及所有元素之和。每次我们计算数组中子数组和小于等于当前枚举值的个数,如果个数大于等于 $k$,则说明当前枚举值 $s$ 可能是第 $k$ 小的子数组和,我们缩小右边界,否则我们增大左边界。枚举结束后,左边界即为第 $k$ 小的子数组和。
69+
70+
问题转换为计算一个数组中,有多少个子数组的和小于等于 $s$,我们可以通过函数 $f(s)$ 来计算。
71+
72+
函数 $f(s)$ 的计算方法如下:
73+
74+
- 初始化双指针 $j$ 和 $i$,分别指向当前窗口的左右边界,初始时 $j = i = 0$。初始化窗口内元素的和 $t = 0$。
75+
- 用变量 $cnt$ 记录子数组和小于等于 $s$ 的个数,初始时 $cnt = 0$。
76+
- 遍历数组 $nums$,每次遍历到一个元素 $nums[i]$,我们将其加入窗口,即 $t = t + nums[i]$。如果此时 $t \gt s$,我们需要不断地将窗口的左边界右移,直到 $t \le s$ 为止,即不断地执行 $t -= nums[j]$,并且 $j = j + 1$。接下来我们更新 $cnt$,即 $cnt = cnt + i - j + 1$。继续遍历下一个元素,直到遍历完整个数组。
77+
78+
最后将 $cnt$ 作为函数 $f(s)$ 的返回值。
79+
80+
时间复杂度 $O(n \times \log S)$,空间复杂度 $O(1)$。其中 $n$ 为数组 $nums$ 的长度,而 $S$ 为数组 $nums$ 中所有元素之和。
81+
6482
<!-- tabs:start -->
6583

6684
### **Python3**
6785

6886
<!-- 这里可写当前语言的特殊实现逻辑 -->
6987

7088
```python
71-
89+
class Solution:
90+
def kthSmallestSubarraySum(self, nums: List[int], k: int) -> int:
91+
def f(s):
92+
t = j = 0
93+
cnt = 0
94+
for i, x in enumerate(nums):
95+
t += x
96+
while t > s:
97+
t -= nums[j]
98+
j += 1
99+
cnt += i - j + 1
100+
return cnt >= k
101+
102+
l, r = min(nums), sum(nums)
103+
return l + bisect_left(range(l, r + 1), True, key=f)
72104
```
73105

74106
### **Java**
75107

76108
<!-- 这里可写当前语言的特殊实现逻辑 -->
77109

78110
```java
111+
class Solution {
112+
public int kthSmallestSubarraySum(int[] nums, int k) {
113+
int l = 1 << 30, r = 0;
114+
for (int x : nums) {
115+
l = Math.min(l, x);
116+
r += x;
117+
}
118+
while (l < r) {
119+
int mid = (l + r) >> 1;
120+
if (f(nums, mid) >= k) {
121+
r = mid;
122+
} else {
123+
l = mid + 1;
124+
}
125+
}
126+
return l;
127+
}
128+
129+
private int f(int[] nums, int s) {
130+
int t = 0, j = 0;
131+
int cnt = 0;
132+
for (int i = 0; i < nums.length; ++i) {
133+
t += nums[i];
134+
while (t > s) {
135+
t -= nums[j++];
136+
}
137+
cnt += i - j + 1;
138+
}
139+
return cnt;
140+
}
141+
}
142+
```
143+
144+
### **C++**
145+
146+
```cpp
147+
class Solution {
148+
public:
149+
int kthSmallestSubarraySum(vector<int>& nums, int k) {
150+
int l = 1 << 30, r = 0;
151+
for (int& x : nums) {
152+
l = min(l, x);
153+
r += x;
154+
}
155+
auto f = [&](int s) {
156+
int cnt = 0, t = 0;
157+
for (int i = 0, j = 0; i < nums.size(); ++i) {
158+
t += nums[i];
159+
while (t > s) {
160+
t -= nums[j++];
161+
}
162+
cnt += i - j + 1;
163+
}
164+
return cnt;
165+
};
166+
while (l < r) {
167+
int mid = (l + r) >> 1;
168+
if (f(mid) >= k) {
169+
r = mid;
170+
} else {
171+
l = mid + 1;
172+
}
173+
}
174+
return l;
175+
}
176+
};
177+
```
79178
179+
### **Go**
180+
181+
```go
182+
func kthSmallestSubarraySum(nums []int, k int) int {
183+
l, r := 1<<30, 0
184+
for _, x := range nums {
185+
l = min(l, x)
186+
r += x
187+
}
188+
f := func(s int) (cnt int) {
189+
t := 0
190+
for i, j := 0, 0; i < len(nums); i++ {
191+
t += nums[i]
192+
for t > s {
193+
t -= nums[j]
194+
j++
195+
}
196+
cnt += i - j + 1
197+
}
198+
return
199+
}
200+
for l < r {
201+
mid := (l + r) >> 1
202+
if f(mid) >= k {
203+
r = mid
204+
} else {
205+
l = mid + 1
206+
}
207+
}
208+
return l
209+
}
210+
211+
func min(a, b int) int {
212+
if a < b {
213+
return a
214+
}
215+
return b
216+
}
80217
```
81218

82219
### **...**

solution/1900-1999/1918.Kth Smallest Subarray Sum/README_EN.md

Lines changed: 120 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,132 @@ Ordering the sums from smallest to largest gives 3, 3, 5, 5, 6, 8, <u>10</u>, 11
6060
### **Python3**
6161

6262
```python
63-
63+
class Solution:
64+
def kthSmallestSubarraySum(self, nums: List[int], k: int) -> int:
65+
def f(s):
66+
t = j = 0
67+
cnt = 0
68+
for i, x in enumerate(nums):
69+
t += x
70+
while t > s:
71+
t -= nums[j]
72+
j += 1
73+
cnt += i - j + 1
74+
return cnt >= k
75+
76+
l, r = min(nums), sum(nums)
77+
return l + bisect_left(range(l, r + 1), True, key=f)
6478
```
6579

6680
### **Java**
6781

6882
```java
83+
class Solution {
84+
public int kthSmallestSubarraySum(int[] nums, int k) {
85+
int l = 1 << 30, r = 0;
86+
for (int x : nums) {
87+
l = Math.min(l, x);
88+
r += x;
89+
}
90+
while (l < r) {
91+
int mid = (l + r) >> 1;
92+
if (f(nums, mid) >= k) {
93+
r = mid;
94+
} else {
95+
l = mid + 1;
96+
}
97+
}
98+
return l;
99+
}
100+
101+
private int f(int[] nums, int s) {
102+
int t = 0, j = 0;
103+
int cnt = 0;
104+
for (int i = 0; i < nums.length; ++i) {
105+
t += nums[i];
106+
while (t > s) {
107+
t -= nums[j++];
108+
}
109+
cnt += i - j + 1;
110+
}
111+
return cnt;
112+
}
113+
}
114+
```
115+
116+
### **C++**
117+
118+
```cpp
119+
class Solution {
120+
public:
121+
int kthSmallestSubarraySum(vector<int>& nums, int k) {
122+
int l = 1 << 30, r = 0;
123+
for (int& x : nums) {
124+
l = min(l, x);
125+
r += x;
126+
}
127+
auto f = [&](int s) {
128+
int cnt = 0, t = 0;
129+
for (int i = 0, j = 0; i < nums.size(); ++i) {
130+
t += nums[i];
131+
while (t > s) {
132+
t -= nums[j++];
133+
}
134+
cnt += i - j + 1;
135+
}
136+
return cnt;
137+
};
138+
while (l < r) {
139+
int mid = (l + r) >> 1;
140+
if (f(mid) >= k) {
141+
r = mid;
142+
} else {
143+
l = mid + 1;
144+
}
145+
}
146+
return l;
147+
}
148+
};
149+
```
69150
151+
### **Go**
152+
153+
```go
154+
func kthSmallestSubarraySum(nums []int, k int) int {
155+
l, r := 1<<30, 0
156+
for _, x := range nums {
157+
l = min(l, x)
158+
r += x
159+
}
160+
f := func(s int) (cnt int) {
161+
t := 0
162+
for i, j := 0, 0; i < len(nums); i++ {
163+
t += nums[i]
164+
for t > s {
165+
t -= nums[j]
166+
j++
167+
}
168+
cnt += i - j + 1
169+
}
170+
return
171+
}
172+
for l < r {
173+
mid := (l + r) >> 1
174+
if f(mid) >= k {
175+
r = mid
176+
} else {
177+
l = mid + 1
178+
}
179+
}
180+
return l
181+
}
182+
183+
func min(a, b int) int {
184+
if a < b {
185+
return a
186+
}
187+
return b
188+
}
70189
```
71190

72191
### **...**
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
class Solution {
2+
public:
3+
int kthSmallestSubarraySum(vector<int>& nums, int k) {
4+
int l = 1 << 30, r = 0;
5+
for (int& x : nums) {
6+
l = min(l, x);
7+
r += x;
8+
}
9+
auto f = [&](int s) {
10+
int cnt = 0, t = 0;
11+
for (int i = 0, j = 0; i < nums.size(); ++i) {
12+
t += nums[i];
13+
while (t > s) {
14+
t -= nums[j++];
15+
}
16+
cnt += i - j + 1;
17+
}
18+
return cnt;
19+
};
20+
while (l < r) {
21+
int mid = (l + r) >> 1;
22+
if (f(mid) >= k) {
23+
r = mid;
24+
} else {
25+
l = mid + 1;
26+
}
27+
}
28+
return l;
29+
}
30+
};
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
func kthSmallestSubarraySum(nums []int, k int) int {
2+
l, r := 1<<30, 0
3+
for _, x := range nums {
4+
l = min(l, x)
5+
r += x
6+
}
7+
f := func(s int) (cnt int) {
8+
t := 0
9+
for i, j := 0, 0; i < len(nums); i++ {
10+
t += nums[i]
11+
for t > s {
12+
t -= nums[j]
13+
j++
14+
}
15+
cnt += i - j + 1
16+
}
17+
return
18+
}
19+
for l < r {
20+
mid := (l + r) >> 1
21+
if f(mid) >= k {
22+
r = mid
23+
} else {
24+
l = mid + 1
25+
}
26+
}
27+
return l
28+
}
29+
30+
func min(a, b int) int {
31+
if a < b {
32+
return a
33+
}
34+
return b
35+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
class Solution {
2+
public int kthSmallestSubarraySum(int[] nums, int k) {
3+
int l = 1 << 30, r = 0;
4+
for (int x : nums) {
5+
l = Math.min(l, x);
6+
r += x;
7+
}
8+
while (l < r) {
9+
int mid = (l + r) >> 1;
10+
if (f(nums, mid) >= k) {
11+
r = mid;
12+
} else {
13+
l = mid + 1;
14+
}
15+
}
16+
return l;
17+
}
18+
19+
private int f(int[] nums, int s) {
20+
int t = 0, j = 0;
21+
int cnt = 0;
22+
for (int i = 0; i < nums.length; ++i) {
23+
t += nums[i];
24+
while (t > s) {
25+
t -= nums[j++];
26+
}
27+
cnt += i - j + 1;
28+
}
29+
return cnt;
30+
}
31+
}

0 commit comments

Comments
 (0)