Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit dfdc29d

Browse files
Merge pull request SharingSource#122 from SharingSource/ac_oier
✨feat: Add 528
2 parents f08f645 + 165d33c commit dfdc29d

File tree

4 files changed

+171
-0
lines changed

4 files changed

+171
-0
lines changed

‎Index/二分.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
| [354. 俄罗斯套娃信封问题](https://leetcode-cn.com/problems/russian-doll-envelopes/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/russian-doll-envelopes/solution/zui-chang-shang-sheng-zi-xu-lie-bian-xin-6s8d/) | 困难 | 🤩🤩🤩 |
1717
| [363. 矩形区域不超过 K 的最大数值和](https://leetcode-cn.com/problems/max-sum-of-rectangle-no-larger-than-k/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/max-sum-of-rectangle-no-larger-than-k/solution/gong-shui-san-xie-you-hua-mei-ju-de-ji-b-dh8s/) | 困难 | 🤩🤩🤩 |
1818
| [374. 猜数字大小](https://leetcode-cn.com/problems/guess-number-higher-or-lower/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/guess-number-higher-or-lower/solution/gong-shui-san-xie-shi-yong-jiao-hu-han-s-tocm/) | 简单 | 🤩🤩🤩 |
19+
| [528. 按权重随机选择](https://leetcode-cn.com/problems/random-pick-with-weight/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/random-pick-with-weight/solution/gong-shui-san-xie-yi-ti-shuang-jie-qian-8bx50/) | 中等 | 🤩🤩🤩🤩 |
1920
| [611. 有效三角形的个数](https://leetcode-cn.com/problems/valid-triangle-number/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/valid-triangle-number/solution/gong-shui-san-xie-yi-ti-san-jie-jian-dan-y1we/) | 中等 | 🤩🤩🤩🤩 |
2021
| [778. 水位上升的泳池中游泳](https://leetcode-cn.com/problems/swim-in-rising-water/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/swim-in-rising-water/solution/gong-shui-san-xie-yi-ti-shuang-jie-krusk-7c6o/) | 困难 | 🤩🤩🤩 |
2122
| [852. 山脉数组的峰顶索引](https://leetcode-cn.com/problems/peak-index-in-a-mountain-array/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/peak-index-in-a-mountain-array/solution/gong-shui-san-xie-er-fen-san-fen-cha-zhi-5gfv/) | 简单 | 🤩🤩🤩🤩🤩 |

‎Index/前缀和.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
| [363. 矩形区域不超过 K 的最大数值和](https://leetcode-cn.com/problems/max-sum-of-rectangle-no-larger-than-k/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/max-sum-of-rectangle-no-larger-than-k/solution/gong-shui-san-xie-you-hua-mei-ju-de-ji-b-dh8s/) | 困难 | 🤩🤩🤩 |
66
| [523. 连续的子数组和](https://leetcode-cn.com/problems/continuous-subarray-sum/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/continuous-subarray-sum/solution/gong-shui-san-xie-tuo-zhan-wei-qiu-fang-1juse/) | 中等 | 🤩🤩🤩🤩 |
77
| [525. 连续数组](https://leetcode-cn.com/problems/contiguous-array/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/contiguous-array/solution/gong-shui-san-xie-qian-zhui-he-ha-xi-bia-q400/) | 中等 | 🤩🤩🤩🤩 |
8+
| [528. 按权重随机选择](https://leetcode-cn.com/problems/random-pick-with-weight/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/random-pick-with-weight/solution/gong-shui-san-xie-yi-ti-shuang-jie-qian-8bx50/) | 中等 | 🤩🤩🤩🤩 |
89
| [724. 寻找数组的中心下标](https://leetcode-cn.com/problems/find-pivot-index/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/find-pivot-index/solution/shi-yong-shao-bing-ji-qiao-liang-bian-qi-vkju/) | 简单 | 🤩🤩🤩🤩🤩 |
910
| [930. 和相同的二元子数组](https://leetcode-cn.com/problems/binary-subarrays-with-sum/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/binary-subarrays-with-sum/solution/gong-shui-san-xie-yi-ti-shuang-jie-qian-hfoc0/) | 中等 | 🤩🤩🤩 |
1011
| [1004. 最大连续1的个数 III](https://leetcode-cn.com/problems/max-consecutive-ones-iii/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/max-consecutive-ones-iii/solution/san-chong-jie-fa-cong-dong-tai-gui-hua-d-gxks/) | 中等 | 🤩🤩🤩 |

‎Index/模拟.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
| [443. 压缩字符串](https://leetcode-cn.com/problems/string-compression/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/string-compression/solution/gong-shui-san-xie-shuang-zhi-zhen-yuan-d-bppu/) | 中等 | 🤩🤩🤩🤩 |
2727
| [451. 根据字符出现频率排序](https://leetcode-cn.com/problems/sort-characters-by-frequency/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/sort-characters-by-frequency/solution/gong-shui-san-xie-shu-ju-jie-gou-yun-yon-gst9/) | 中等 | 🤩🤩🤩🤩 |
2828
| [457. 环形数组是否存在循环](https://leetcode-cn.com/problems/circular-array-loop/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/circular-array-loop/solution/gong-shui-san-xie-yi-ti-shuang-jie-mo-ni-ag05/) | 中等 | 🤩🤩🤩🤩 |
29+
| [528. 按权重随机选择](https://leetcode-cn.com/problems/random-pick-with-weight/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/random-pick-with-weight/solution/gong-shui-san-xie-yi-ti-shuang-jie-qian-8bx50/) | 中等 | 🤩🤩🤩🤩 |
2930
| [541. 反转字符串 II](https://leetcode-cn.com/problems/reverse-string-ii/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/reverse-string-ii/solution/gong-shui-san-xie-jian-dan-zi-fu-chuan-m-p88f/) | 简单 | 🤩🤩🤩🤩🤩 |
3031
| [551. 学生出勤记录 I](https://leetcode-cn.com/problems/student-attendance-record-i/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/student-attendance-record-i/solution/gong-shui-san-xie-jian-dan-mo-ni-ti-by-a-hui7/) | 简单 | 🤩🤩🤩 |
3132
| [566. 重塑矩阵](https://leetcode-cn.com/problems/reshape-the-matrix/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/reshape-the-matrix/solution/jian-dan-ti-zhong-quan-chu-ji-ke-yi-kan-79gv5/) | 简单 | 🤩🤩🤩 |
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
### 题目描述
2+
3+
这是 LeetCode 上的 **[528. 按权重随机选择](https://leetcode-cn.com/problems/random-pick-with-weight/solution/gong-shui-san-xie-yi-ti-shuang-jie-qian-8bx50/)** ,难度为 **中等**
4+
5+
Tag : 「前缀和」、「二分」、「模拟」
6+
7+
8+
9+
给定一个正整数数组 w ,其中 w[i] 代表下标 i 的权重(下标从 0 开始),请写一个函数 pickIndex ,它可以随机地获取下标 i,选取下标 i 的概率与 w[i] 成正比。
10+
11+
例如,对于 w = [1, 3],挑选下标 0 的概率为 1 / (1 + 3) = 0.25 (即,25%),而选取下标 1 的概率为 3 / (1 + 3) = 0.75(即,75%)。
12+
13+
也就是说,选取下标 i 的概率为 w[i] / sum(w) 。
14+
15+
示例 1:
16+
```
17+
输入:
18+
["Solution","pickIndex"]
19+
[[[1]],[]]
20+
21+
输出:
22+
[null,0]
23+
24+
解释:
25+
Solution solution = new Solution([1]);
26+
solution.pickIndex(); // 返回 0,因为数组中只有一个元素,所以唯一的选择是返回下标 0。
27+
```
28+
示例 2:
29+
```
30+
输入:
31+
["Solution","pickIndex","pickIndex","pickIndex","pickIndex","pickIndex"]
32+
[[[1,3]],[],[],[],[],[]]
33+
34+
输出:
35+
[null,1,1,1,1,0]
36+
37+
解释:
38+
Solution solution = new Solution([1, 3]);
39+
solution.pickIndex(); // 返回 1,返回下标 1,返回该下标概率为 3/4 。
40+
solution.pickIndex(); // 返回 1
41+
solution.pickIndex(); // 返回 1
42+
solution.pickIndex(); // 返回 1
43+
solution.pickIndex(); // 返回 0,返回下标 0,返回该下标概率为 1/4 。
44+
45+
由于这是一个随机问题,允许多个答案,因此下列输出都可以被认为是正确的:
46+
[null,1,1,1,1,0]
47+
[null,1,1,1,1,1]
48+
[null,1,1,1,0,0]
49+
[null,1,1,1,0,1]
50+
[null,1,0,1,0,0]
51+
......
52+
诸若此类。
53+
```
54+
55+
提示:
56+
* 1 <= w.length <= 10000
57+
* 1 <= w[i] <= 10ドル^5$
58+
* pickIndex 将被调用不超过 10000 次
59+
60+
---
61+
62+
### 前缀和 + 二分
63+
64+
根据题意,权重值 $w[i]$ 可以作为 `pickIndex` 调用总次数为 $\sum_{i = 0}^{w.length - 1} w[i]$ 时,下标 $i$ 的返回次数。
65+
66+
随机数的产生可以直接使用语言自带的 API,剩下的我们需要构造一个分布符合权重的序列。
67+
68+
由于 1ドル <= w[i] <= 10^5,ドル且 $w$ 长度为 10ドル^4,ドル因此直接使用构造一个有 $w[i]$ 个的 $i$ 的数字会 MLE。
69+
70+
**我们可以使用「前缀和」数组来作为权重分布序列,权重序列的基本单位为 1ドル$。**
71+
72+
一个长度为 $n$ 的构造好的「前缀和」数组可以看是一个基本单位为 1ドル$ 的 $[1, sum[n - 1]]$ 数轴。
73+
74+
使用随机函数参数产生 $[1, sum[n - 1]]$ 范围内的随机数,通过「二分」前缀和数组即可找到分布位置对应的原始下标值。
75+
76+
![image.png](https://pic.leetcode-cn.com/1630289210-kRFEDD-image.png)
77+
78+
代码:
79+
```Java
80+
class Solution {
81+
int[] sum;
82+
public Solution(int[] w) {
83+
int n = w.length;
84+
sum = new int[n + 1];
85+
for (int i = 1; i <= n; i++) sum[i] = sum[i - 1] + w[i - 1];
86+
}
87+
88+
public int pickIndex() {
89+
int n = sum.length;
90+
int t = (int) (Math.random() * sum[n - 1]) + 1;
91+
int l = 1, r = n - 1;
92+
while (l < r) {
93+
int mid = l + r >> 1;
94+
if (sum[mid] >= t) r = mid;
95+
else l = mid + 1;
96+
}
97+
return r - 1;
98+
}
99+
}
100+
```
101+
* 时间复杂度:`Solution` 类的构造方法整体复杂度为 $O(n)$;`pickIndex` 的复杂度为 $O(\log{n})$
102+
* 空间复杂度:$O(n)$
103+
104+
---
105+
106+
### 模拟(桶轮询)
107+
108+
利用 OJ 不太聪明(对权重分布做近似检查),我们可以构造一个最小轮询序列(权重精度保留到小数点一位),并使用 $(i, cnt)$ 的形式进行存储,代表下标 $i$ 在最小轮询序列中出现次数为 $cnt$。
109+
110+
然后使用两个编号 $bid$ 和 $iid$ 来对桶进行轮询返回(循环重置 & 跳到下一个桶)。
111+
112+
**该解法的最大好处是不需要使用 random 函数,同时返回的连续序列满足每一段(长度不短于最小段)都符合近似权重分布。**
113+
114+
![image.png](https://pic.leetcode-cn.com/1630291157-nubqik-image.png)
115+
116+
代码:
117+
```Java
118+
class Solution {
119+
// 桶编号 / 桶内编号 / 总数
120+
int bid, iid, tot;
121+
List<int[]> list = new ArrayList<>();
122+
public Solution(int[] w) {
123+
int n = w.length;
124+
double sum = 0, min = 1e9;
125+
for (int i : w) {
126+
sum += i;
127+
min = Math.min(min, i);
128+
}
129+
double minv = min / sum;
130+
int k = 1;
131+
while (minv * k < 1) k *= 10;
132+
for (int i = 0; i < n; i++) {
133+
int cnt = (int)(w[i] / sum * k);
134+
list.add(new int[]{i, cnt});
135+
tot += cnt;
136+
}
137+
}
138+
139+
public int pickIndex() {
140+
if (bid >= list.size()) {
141+
bid = 0; iid = 0;
142+
}
143+
int[] info = list.get(bid);
144+
int id = info[0], cnt = info[1];
145+
if (iid >= cnt) {
146+
bid++; iid = 0;
147+
return pickIndex();
148+
}
149+
iid++;
150+
return id;
151+
}
152+
}
153+
```
154+
* 时间复杂度:计算 $k$ 的操作只会发生一次,可以看作是一个均摊到每个下标的常数计算,`Solution` 类的构造方法的整体复杂度可看作 $O(n)$;`pickIndex` 的复杂度为 $O(1)$
155+
* 空间复杂度:$O(n)$
156+
157+
---
158+
159+
### 最后
160+
161+
这是我们「刷穿 LeetCode」系列文章的第 `No.528` 篇,系列开始于 2021年01月01日,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。
162+
163+
在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。
164+
165+
为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode
166+
167+
在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。
168+

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /