forked from Wang-Jun-Chao/coding-interviews
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Test30.java
365 lines (309 loc) · 10.7 KB
/
Test30.java
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
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Author: 王俊超
* Date: 2015-06-10
* Time: 13:32
* Declaration: All Rights Reserved !!!
*/
public class Test30 {
/**
* 大顶堆
*
* @param <T> 参数化类型
*/
private final static class MaxHeap<T extends Comparable<T>> {
// 堆中元素存放的集合
private List<T> items;
// 用于计数
private int cursor;
/**
* 构造一个椎,始大小是32
*/
public MaxHeap() {
this(32);
}
/**
* 造诣一个指定初始大小的堆
*
* @param size 初始大小
*/
public MaxHeap(int size) {
items = new ArrayList<>(size);
cursor = -1;
}
/**
* 向上调整堆
*
* @param index 被上移元素的起始位置
*/
public void siftUp(int index) {
T intent = items.get(index); // 获取开始调整的元素对象
while (index > 0) { // 如果不是根元素
int parentIndex = (index - 1) / 2; // 找父元素对象的位置
T parent = items.get(parentIndex); // 获取父元素对象
if (intent.compareTo(parent) > 0) { //上移的条件,子节点比父节点大
items.set(index, parent); // 将父节点向下放
index = parentIndex; // 记录父节点下放的位置
} else { // 子节点不比父节点大,说明父子路径已经按从大到小排好顺序了,不需要调整了
break;
}
}
// index此时记录是的最后一个被下放的父节点的位置(也可能是自身),所以将最开始的调整的元素值放入index位置即可
items.set(index, intent);
}
/**
* 向下调整堆
*
* @param index 被下移的元素的起始位置
*/
public void siftDown(int index) {
T intent = items.get(index); // 获取开始调整的元素对象
int leftIndex = 2 * index + 1; // // 获取开始调整的元素对象的左子结点的元素位置
while (leftIndex < items.size()) { // 如果有左子结点
T maxChild = items.get(leftIndex); // 取左子结点的元素对象,并且假定其为两个子结点中最大的
int maxIndex = leftIndex; // 两个子节点中最大节点元素的位置,假定开始时为左子结点的位置
int rightIndex = leftIndex + 1; // 获取右子结点的位置
if (rightIndex < items.size()) { // 如果有右子结点
T rightChild = items.get(rightIndex); // 获取右子结点的元素对象
if (rightChild.compareTo(maxChild) > 0) { // 找出两个子节点中的最大子结点
maxChild = rightChild;
maxIndex = rightIndex;
}
}
// 如果最大子节点比父节点大,则需要向下调整
if (maxChild.compareTo(intent) > 0) {
items.set(index, maxChild); // 将子节点向上移
index = maxIndex; // 记录上移节点的位置
leftIndex = index * 2 + 1; // 找到上移节点的左子节点的位置
} else { // 最大子节点不比父节点大,说明父子路径已经按从大到小排好顺序了,不需要调整了
break;
}
}
// index此时记录是的最后一个被上移的子节点的位置(也可能是自身),所以将最开始的调整的元素值放入index位置即可
items.set(index, intent);
}
/**
* 向堆中添加一个元素
*
* @param item 等待添加的元素
*/
public void add(T item) {
items.add(item); // 将元素添加到最后
siftUp(items.size() - 1); // 循环上移,以完成重构
}
/**
* 删除堆顶元素
*
* @return 堆顶部的元素
*/
public T deleteTop() {
if (items.isEmpty()) { // 如果堆已经为空,就报出异常
throw new RuntimeException("The heap is empty.");
}
T maxItem = items.get(0); // 获取堆顶元素
T lastItem = items.remove(items.size() - 1); // 删除最后一个元素
if (items.isEmpty()) { // 删除元素后,如果堆为空的情况,说明删除的元素也是堆顶元素
return lastItem;
}
items.set(0, lastItem); // 将删除的元素放入堆顶
siftDown(0); // 自上向下调整堆
return maxItem; // 返回堆顶元素
}
/**
* 获取下一个元素
*
* @return 下一个元素对象
*/
public T next() {
if (cursor >= items.size()) {
throw new RuntimeException("No more element");
}
return items.get(cursor);
}
/**
* 判断堆中是否还有下一个元素
*
* @return true堆中还有下一个元素,false堆中无下五元素
*/
public boolean hasNext() {
cursor++;
return cursor < items.size();
}
/**
* 获取堆中的第一个元素
*
* @return 堆中的第一个元素
*/
public T first() {
if (items.size() == 0) {
throw new RuntimeException("The heap is empty.");
}
return items.get(0);
}
/**
* 判断堆是否为空
*
* @return true是,false否
*/
public boolean isEmpty() {
return items.isEmpty();
}
/**
* 获取堆的大小
*
* @return 堆的大小
*/
public int size() {
return items.size();
}
/**
* 清空堆
*/
public void clear() {
items.clear();
}
@Override
public String toString() {
return items.toString();
}
}
/**
* 题目: 输入n个整数,找出其中最小的k个数。
* 【第二种解法】
* @param input 输入数组
* @param output 输出数组
*/
public static void getLeastNumbers2(int[] input, int[] output) {
if (input == null || output == null || output.length <= 0 || input.length < output.length) {
throw new IllegalArgumentException("Invalid args");
}
MaxHeap<Integer> maxHeap = new MaxHeap<>(output.length);
for (int i : input) {
if (maxHeap.size() < output.length) {
maxHeap.add(i);
} else {
int max = maxHeap.first();
if (max > i) {
maxHeap.deleteTop();
maxHeap.add(i);
}
}
}
for (int i = 0; maxHeap.hasNext(); i++) {
output[i] = maxHeap.next();
}
}
/**
* 题目: 输入n个整数,找出其中最小的k个数。
* 【第一种解法】
* @param input 输入数组
* @param output 输出数组
*/
public static void getLeastNumbers(int[] input, int[] output) {
if (input == null || output == null || output.length <= 0 || input.length < output.length) {
throw new IllegalArgumentException("Invalid args");
}
int start = 0;
int end = input.length - 1;
int index = partition(input, start, end);
int target = output.length - 1;
while (index != target) {
if (index < target) {
start = index + 1;
} else {
end = index - 1;
}
index = partition(input, start, end);
}
System.arraycopy(input, 0, output, 0, output.length);
}
/**
* 分区算法
*
* @param input 输入数组
* @param start 开始下标
* @param end 结束下标
* @return 分区位置
*/
private static int partition(int[] input, int start, int end) {
int tmp = input[start];
while (start < end) {
while (start < end && input[end] >= tmp) {
end--;
}
input[start] = input[end];
while (start < end && input[start] <= tmp) {
start++;
}
input[end] = input[start];
}
input[start] = tmp;
return start;
}
public static void main(String[] args) {
System.out.println("第一种解法:");
test1();
System.out.println();
System.out.println("第二种解法:");
test2();
}
private static void test1() {
int[] data = {4, 5, 1, 6, 2, 7, 3, 8};
int[] output = new int[4];
getLeastNumbers(data, output);
for (int i : output) {
System.out.print(i + " ");
}
System.out.println();
int[] output2 = new int[8];
getLeastNumbers(data, output2);
for (int i : output2) {
System.out.print(i + " ");
}
System.out.println();
int[] output3 = new int[1];
getLeastNumbers(data, output3);
for (int i : output3) {
System.out.print(i + " ");
}
System.out.println();
int[] data2 = {4, 5, 1, 6, 2, 7, 2, 8};
int[] output4 = new int[2];
getLeastNumbers(data2, output4);
for (int i : output4) {
System.out.print(i + " ");
}
System.out.println();
}
private static void test2() {
int[] data = {4, 5, 1, 6, 2, 7, 3, 8};
int[] output = new int[4];
getLeastNumbers2(data, output);
for (int i : output) {
System.out.print(i + " ");
}
System.out.println();
int[] output2 = new int[8];
getLeastNumbers2(data, output2);
for (int i : output2) {
System.out.print(i + " ");
}
System.out.println();
int[] output3 = new int[1];
getLeastNumbers2(data, output3);
for (int i : output3) {
System.out.print(i + " ");
}
System.out.println();
int[] data2 = {4, 5, 1, 6, 2, 7, 2, 8};
int[] output4 = new int[2];
getLeastNumbers2(data2, output4);
for (int i : output4) {
System.out.print(i + " ");
}
System.out.println();
}
}