0%

algorithm-heap

简单

数组中的第K个最大元素

题目描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。

请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。

你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。



示例 1:

输入: [3,2,1,5,6,4], k = 2
输出: 5
示例 2:

输入: [3,2,3,1,2,4,5,5,6], k = 4
输出: 4


提示:

1 <= k <= nums.length <= 105
-104 <= nums[i] <= 104

题目解答

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
public class Solution {
public int findKthLargest(int[] nums, int k) {
if (nums.length < k) {
return 0;
}

genHeap(nums);

int len = nums.length;
while (len > 1) {
swap(nums, 0, --len);
shiftDown(nums, 0, len);

k--;
if (k == 0) {
break;
}
}

return nums[k == 0 ? len : 0];
}

private void genHeap(int[] nums) {
int len = nums.length;
for (int i = (len - 2) / 2; i >= 0; i--) {
shiftDown(nums, i, len);
}
}

private void shiftDown(int[] nums, int i, int heapSize) {
int j = 2 * i + 1;
while (j < heapSize) {
// 大顶堆,选择左右结点中较大的那一个的下标
j = j + 1 < heapSize && nums[j + 1] > nums[j] ? j + 1 : j;
if (nums[j] > nums[i]) {
// 大顶堆,谁大谁在上
swap(nums, j, i);

i = j;
j = 2 * i + 1;
} else {
break;
}
}
}

private static void swap(int[] array, int i, int j) {
// 注释掉,因为每次判断带来的开销并不比无效的自我交换带来的开销少
// if (i == j) {
// return;
// }

int t = array[i];
array[i] = array[j];
array[j] = t;
}
}

class TestMain {

public static void main(String[] args) {
TestUtils.runTestCases(TestCase.class);
}

public static class TestCase {

public static boolean testCase1() {
int[] nums = { 3, 2, 1, 5, 6, 4 };
int k = 2;

int result = new Solution().findKthLargest(nums, k);
int expect = 5;

return TestUtils.check(result, expect);
}

public static boolean testCase2() {
int[] nums = { 3, 2, 3, 1, 2, 4, 5, 5, 6 };
int k = 4;

int result = new Solution().findKthLargest(nums, k);
int expect = 4;

return TestUtils.check(result, expect);
}

public static boolean testCase3() {
int[] nums = { 4, 5, 1, 3, 2 };
int k = 1;

int result = new Solution().findKthLargest(nums, k);
int expect = 5;

return TestUtils.check(result, expect);
}

public static boolean testCase4() {
int[] nums = { 4, 5, 1, 3, 2 };
int k = 3;

int result = new Solution().findKthLargest(nums, k);
int expect = 3;

return TestUtils.check(result, expect);
}

public static boolean testCase5() {
int[] nums = { 4, 5, 1, 3, 2 };
int k = 5;

int result = new Solution().findKthLargest(nums, k);
int expect = 1;

return TestUtils.check(result, expect);
}

public static boolean testCase6() {
int[] nums = { 2, 1 };
int k = 1;

int result = new Solution().findKthLargest(nums, k);
int expect = 2;

return TestUtils.check(result, expect);
}
}

public static class TestUtils {

public static boolean check(Object result, Object expect) {
result = normalizeObject(result);
expect = normalizeObject(expect);
boolean ok = java.util.Objects.deepEquals(result, expect);
printCheck(toString(result), toString(expect), ok);
return ok;
}

public static boolean check(Object result, String expect) {
boolean ok = java.util.Objects.equals(normalizeString(toString(result)),
normalizeString(toString(expect)));
printCheck(normalizeString(toString(result)), normalizeString(toString(expect)), ok);
return ok;
}

private static Object normalizeObject(Object o) {
if (o instanceof java.util.List) {
java.util.List<?> list = (java.util.List<?>) o;
if (list != null && !list.isEmpty() && list.get(0) instanceof java.util.List) {
o = toArrays(list);
} else {
o = toArray(list);
}
}

return o;
}

private static String toString(Object o) {
if (o instanceof Object[]) {
return java.util.Arrays.deepToString((Object[]) o);
} else if (o instanceof int[]) {
return java.util.Arrays.toString((int[]) o);
} else if (o instanceof double[]) {
return java.util.Arrays.toString((double[]) o);
} else if (o instanceof char[]) {
return java.util.Arrays.toString((char[]) o);
} else {
return java.util.Objects.toString(o);
}
}

private static String normalizeString(String s) {
boolean isArray = (s.startsWith("{") && s.endsWith("}")) || (s.startsWith("[") && s.endsWith("]"));
if (isArray) {
s = s.replace(" ", "")
.replace("'", "")
.replace("\"", "")
.replace("{", "[")
.replace("}", "]");
}

return s;
}

private static void printCheck(String result, String expect, boolean ok) {
// System.out.println();
// System.out.println("--->");

System.out.println("result: " + result);
System.out.println("expect: " + expect);

System.out.println();
if (ok) {
System.out.println("比较结果为: 正确(right)");
} else {
System.out.println("比较结果为: 错误(error)");
}

// System.out.println();
// System.out.println("<---");
}

public static void runTestCases(Class<?> clazz) {
java.lang.reflect.Method[] methods = clazz.getDeclaredMethods();
java.util.Arrays.sort(methods, (o1, o2) -> {
return o1.getName().compareTo(o2.getName());
});
for (java.lang.reflect.Method method : methods) {
if (method.getName().startsWith("test")) {
System.out.println(String.format("--- %s --->", method.getName()));

Object object = null;
try {
object = method.invoke(null);
} catch (Exception e) {
e.printStackTrace();
}

System.out.println(String.format("<--- %s ---", method.getName()));

if (object instanceof Boolean) {
Boolean ok = (Boolean) object;
if (!ok) {
break;
}
} else {
throw new RuntimeException(String.format("测试用例方法%s的返回值需要为布尔类型", method.getName()));
}
}
}
}

public static Object[] toArray(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0];
}

return list.toArray();
}

public static Object[][] toArrays(Object o) {
java.util.List<?> list = (java.util.List<?>) o;
if (list == null || list.isEmpty()) {
return new Object[0][0];
}

Object[][] arrays = new Object[list.size()][];
for (int i = 0; i < list.size(); i++) {
arrays[i] = toArray(list.get(i));
}

return arrays;
}

@SuppressWarnings("unchecked")
public static <T> T[] genArray(Class<T> clazz, int length) {
return (T[]) java.lang.reflect.Array.newInstance(clazz, length);
}

@SuppressWarnings("unchecked")
public static <T> T[][] genArrays(Class<T> clazz, int rows, int cols) {
T[] array = genArray(clazz, 0);

T[][] arrays = (T[][]) genArray(array.getClass(), rows);
for (int i = 0; i < arrays.length; i++) {
arrays[i] = genArray(clazz, cols);
}

return arrays;
}

public static <T> T[] toArray(java.util.List<T> list, Class<T> clazz) {
if (list == null || list.isEmpty()) {
return genArray(clazz, 0);
}

T[] array = genArray(clazz, list.size());
for (int i = 0; i < array.length; i++) {
array[i] = list.get(i);
}

return array;
}

public static <T> T[][] toArrays(java.util.List<java.util.List<T>> lists, Class<T> clazz) {
if (lists == null || lists.isEmpty()) {
return genArrays(clazz, 0, 0);
}

T[][] arrays = genArrays(clazz, lists.size(), 0);
for (int i = 0; i < lists.size(); i++) {
arrays[i] = toArray(lists.get(i), clazz);
}

return arrays;
}

public static <T> java.util.List<T> toList(T[] array) {
return java.util.Arrays.asList(array);
}

public static <T> java.util.List<java.util.List<T>> toLists(T[][] arrays) {
java.util.List<java.util.List<T>> lists = new java.util.ArrayList<>();
for (T[] array : arrays) {
lists.add(toList(array));
}

return lists;
}
}
}

查找和最小的K对数字

题目描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
给定两个以 非递减顺序排列 的整数数组 nums1 和 nums2 , 以及一个整数 k 。

定义一对值 (u,v),其中第一个元素来自 nums1,第二个元素来自 nums2 。

请找到和最小的 k 个数对 (u1,v1), (u2,v2) ... (uk,vk) 。



示例 1:

输入: nums1 = [1,7,11], nums2 = [2,4,6], k = 3
输出: [1,2],[1,4],[1,6]
解释: 返回序列中的前 3 对数:
[1,2],[1,4],[1,6],[7,2],[7,4],[11,2],[7,6],[11,4],[11,6]
示例 2:

输入: nums1 = [1,1,2], nums2 = [1,2,3], k = 2
输出: [1,1],[1,1]
解释: 返回序列中的前 2 对数:
[1,1],[1,1],[1,2],[2,1],[1,2],[2,2],[1,3],[1,3],[2,3]


提示:

1 <= nums1.length, nums2.length <= 105
-109 <= nums1[i], nums2[i] <= 109
nums1 和 nums2 均为 升序排列
1 <= k <= 104
k <= nums1.length * nums2.length

题目解答

1
//

TODO:查找和最小的K对数字

困难

IPO

题目描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
假设 力扣(LeetCode)即将开始 IPO 。为了以更高的价格将股票卖给风险投资公司,力扣 希望在 IPO 之前开展一些项目以增加其资本。 由于资源有限,它只能在 IPO 之前完成最多 k 个不同的项目。帮助 力扣 设计完成最多 k 个不同项目后得到最大总资本的方式。

给你 n 个项目。对于每个项目 i ,它都有一个纯利润 profits[i] ,和启动该项目需要的最小资本 capital[i] 。

最初,你的资本为 w 。当你完成一个项目时,你将获得纯利润,且利润将被添加到你的总资本中。

总而言之,从给定项目中选择 最多 k 个不同项目的列表,以 最大化最终资本 ,并输出最终可获得的最多资本。

答案保证在 32 位有符号整数范围内。



示例 1:

输入:k = 2, w = 0, profits = [1,2,3], capital = [0,1,1]
输出:4
解释:
由于你的初始资本为 0,你仅可以从 0 号项目开始。
在完成后,你将获得 1 的利润,你的总资本将变为 1。
此时你可以选择开始 1 号或 2 号项目。
由于你最多可以选择两个项目,所以你需要完成 2 号项目以获得最大的资本。
因此,输出最后最大化的资本,为 0 + 1 + 3 = 4。
示例 2:

输入:k = 3, w = 0, profits = [1,2,3], capital = [0,1,2]
输出:6


提示:

1 <= k <= 105
0 <= w <= 109
n == profits.length
n == capital.length
1 <= n <= 105
0 <= profits[i] <= 104
0 <= capital[i] <= 109

题目解答

1
//

TODO:IPO

数据流的中位数

题目描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
中位数是有序整数列表中的中间值。如果列表的大小是偶数,则没有中间值,中位数是两个中间值的平均值。

例如 arr = [2,3,4] 的中位数是 3 。
例如 arr = [2,3] 的中位数是 (2 + 3) / 2 = 2.5 。
实现 MedianFinder 类:

MedianFinder() 初始化 MedianFinder 对象。

void addNum(int num) 将数据流中的整数 num 添加到数据结构中。

double findMedian() 返回到目前为止所有元素的中位数。与实际答案相差 10-5 以内的答案将被接受。

示例 1:

输入
["MedianFinder", "addNum", "addNum", "findMedian", "addNum", "findMedian"]
[[], [1], [2], [], [3], []]
输出
[null, null, null, 1.5, null, 2.0]

解释
MedianFinder medianFinder = new MedianFinder();
medianFinder.addNum(1); // arr = [1]
medianFinder.addNum(2); // arr = [1, 2]
medianFinder.findMedian(); // 返回 1.5 ((1 + 2) / 2)
medianFinder.addNum(3); // arr[1, 2, 3]
medianFinder.findMedian(); // return 2.0
提示:

-105 <= num <= 105
在调用 findMedian 之前,数据结构中至少有一个元素
最多 5 * 104 次调用 addNum 和 findMedian

题目解答

1
//

TODO:数据流的中位数

只想买包辣条