-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpriorityQueueUse.java
More file actions
399 lines (336 loc) · 13.1 KB
/
priorityQueueUse.java
File metadata and controls
399 lines (336 loc) · 13.1 KB
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
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.PriorityQueue;
import java.util.stream.Collectors;
public class priorityQueueUse {
public static void main(String args[]) {
priorityQueueUse pqUse = new priorityQueueUse();
int[] arr = pqUse.sortKSorted(new int[] { 2, 1, 4, 8, 6, 9 }, 2);
System.out.println(Arrays.toString(arr));
pqUse.checkMaxHeap(new int[] { 10, 9, 8, 7, 6, 5, 4, 3, 2, 7 });
System.out.println(pqUse.kthLargest(new int[] { 10101, 565, 4921, 60 }, 2));
pqUse.findMedian(new int[] { 6, 2, 1, 3, 7, 5 });
System.out.println();
}
/*
* Given a K sorted array- It is expected that the sorted array is returned.
* K sorted array: The final position of every element is within
* k elements of the current position. For example: [2,1,4,8,6,9] and k = 2.
* Every element's final position is within 2 elements (+2 and -2) to the
* current position.
*
* Solution: Create a heap of size k, add first k elements, remove one by one
* and put it in the array from the starting. This will be done for arr.length -
* k
* times. There will come a time when the last k elements are still available.
* At that time, they will be present in the heap, just remove and put them.
*/
public int[] sortKSorted(int arr[], int k) {
PriorityQueue<Integer> pq = new PriorityQueue<Integer>();
for (int i = 0; i < k; i++) {
pq.add(arr[i]);
}
int i = 0;
while (i < arr.length - k) {
int value = pq.remove();
pq.add(arr[i + k]);
arr[i] = value;
i++;
}
for (int j = arr.length - k; j < arr.length; j++) {
arr[j] = pq.remove();
}
return arr;
// The array should be sorted.
}
// Return K Largest elements of the array.
public ArrayList<Integer> kLargest(int[] input, int k) {
/*
* Another way to create max Priority Queue.
* PriorityQueue<Integer> pq = new
* PriorityQueue<Integer>(Collections.reverseOrder());
*/
maxPriorityQueue maxPQ = new maxPriorityQueue();
PriorityQueue<Integer> pq = new PriorityQueue<Integer>(maxPQ);
ArrayList<Integer> alist = new ArrayList<Integer>();
for (Integer a : input) {
pq.add(a);
}
for (int i = 0; i < k; i++) {
alist.add(pq.remove());
}
return alist;
}
/*
* A better solution will be that instead of adding all
* the elements to the PriorityQueue which takes O(n), we add
* only the first k elements to the pq. Then, for the remaining
* elements, we just have to check if the smallest of the pq is
* larger than the remianing elements. This will take only O(k)
*/
public ArrayList<Integer> kLargest2(int[] input, int k) {
PriorityQueue<Integer> pq = new PriorityQueue<Integer>();
for (int i = 0; i < k; i++) {
pq.add(input[i]);
}
for (int i = k; i < input.length; i++) {
if (pq.peek() < input[i]) {
pq.remove();
pq.add(input[i]);
}
}
return new ArrayList<Integer>(pq);
}
public ArrayList<Integer> kSmallest(int[] input, int k) {
PriorityQueue<Integer> pq = new PriorityQueue<Integer>();
ArrayList<Integer> alist = new ArrayList<Integer>();
for (Integer a : input) {
pq.add(a);
}
for (int i = 0; i < k; i++) {
alist.add(pq.remove());
}
return alist;
}
public class minPriorityQueue implements Comparator<Integer> {
@Override
public int compare(Integer o1, Integer o2) {
if (o1 > o2)
return 1;
if (o1 < o2)
return -1;
return 0;
}
}
public class maxPriorityQueue implements Comparator<Integer> {
@Override
public int compare(Integer o1, Integer o2) {
if (o1 < o2)
return 1;
if (o1 > o2)
return -1;
return 0;
}
}
public boolean checkMaxHeap(int arr[]) {
int parent = 0;
int leftChild, rightChild;
while ((2 * parent + 1) < arr.length) {
leftChild = 2 * parent + 1;
rightChild = 2 * parent + 2;
if (arr[leftChild] > arr[parent]) {
return false;
}
if (arr.length - 1 >= rightChild && arr[rightChild] > arr[parent]) {
return false;
}
parent++;
}
return true;
}
// return the Kth Largest element.
public int kthLargest(int[] input, int k) {
/*
* Create a min heap of size arr.length - K, such that
* the top most element will be the Kth largest element.
* Then for the remaining elemenst check if the peek of
* the queue is larger or not - If yes then we are good.
* If no, then replace.
*/
PriorityQueue<Integer> pq = new PriorityQueue<Integer>();
for (int i = 0; i < k; i++) {
pq.add(input[i]);
}
for (int i = k; i < input.length; i++) {
if (pq.peek() < input[i]) {
pq.remove();
pq.add(input[i]);
}
}
return pq.peek();
}
/*
* Given k different sorted arrays of different sizes,
* we need to merge the given arrays such that result
* should be sorted as well.
*/
public ArrayList<Integer> mergeKSortedArrays(ArrayList<ArrayList<Integer>> input) {
PriorityQueue<Integer> pq = new PriorityQueue<Integer>();
ArrayList<Integer> alist = new ArrayList<Integer>();
for (ArrayList<Integer> list : input) {
for (Integer value : list) {
pq.add(value);
}
}
while (!pq.isEmpty()) {
alist.add(pq.remove());
}
return alist;
}
// We have to print the running Median. For every i-th integer added to the
// running list of integers, print the resulting median.
public void findMedian(int arr[]) {
/*
* Approach: Keep two heaps, one max heap and one min heap.
* The larger elements will be placed in the min heap while the smaller
* elements will be placed in the max heap. Such that at any point, the
* max heap will return the largest of the smaller elements, while the min
* heap will return the smallest of the larger elements. The largest element
* in the max heap will be smaller than the smallest element in the min heap.
* The average of removal of both the heaps will be the median, if there
* are even number of elements. If there are odd number of elements, then
* the removal will happen from the larger of the two heaps, which will
* be the median.
*
* This whole idea works only when elements are added in the correct order.
* Always maintain: abs(maxHeap.size - minHeap.size) <= 1
*
* Add first element to max heap.
* If maxHeap.peek() > new element -> Add new element to max heap, and existing
* to min heap.
* If maxHeap.peek() < new element -> Add new element into min heap.
*
* Now, we have following three items:
* minHeap.peek(), maxHeap.peek() and new element.
* Remember: minHeap.peek() > maxHeap.peek(), This should be maintained always.
*
* new-element > minHeap.peek(),
* If size of min Heap is greater, remove one from minHeap, add to the maxheap
* and add the new element to the min Heap. Otherwise just add to the min heap.
*
* new-element < maxHeap.peek(),
* If size of max Heap is greater, remove one from maxHeap, add to the minheap
* and add the new element to the max Heap. Otherwise just add to the max heap.
*
* maxHeap.peek() < new-element < minHeap.peek()
* Just add the element into the smaller heap. If sizes are same, add to the one
* where difference between the peek and the new element is smaller.
*
* At any point, when we have to print the median, we will not actually remove
* the element, but just have a look at the peek(), since who will do the task
* of
* adding the elements back into the respective heaps.
*/
if (arr.length == 0) {
System.out.println(arr.length);
return;
} else if (arr.length == 1) {
System.out.println(arr[0]);
return;
}
PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(Collections.reverseOrder());
PriorityQueue<Integer> minHeap = new PriorityQueue<Integer>();
int minHeap_size = 0;
int maxHeap_size = 0;
// Add the first element to the max heap.
maxHeap.add(arr[0]);
System.out.println(maxHeap.peek());
for (int i = 1; i < arr.length; i++) {
minHeap_size = minHeap.size();
maxHeap_size = maxHeap.size();
if (maxHeap_size > minHeap_size) {
if (maxHeap.peek() > arr[i]) {
minHeap.add(maxHeap.remove());
maxHeap.add(arr[i]);
} else if (minHeap.peek() < arr[i]) {
minHeap.add(arr[i]);
} else {
minHeap.add(arr[i]);
}
} else if (maxHeap_size < minHeap_size) {
if (maxHeap.peek() > arr[i]) {
maxHeap.add(arr[i]);
} else if (minHeap.peek() < arr[i]) {
maxHeap.add(minHeap.remove());
minHeap.add(arr[i]);
} else {
maxHeap.add(arr[i]);
}
} else {
if (Math.abs(maxHeap.peek() - arr[i]) > Math.abs(minHeap.peek() - arr[i])) {
minHeap.add(arr[i]);
} else if (Math.abs(maxHeap.peek() - arr[i]) < Math.abs(minHeap.peek() - arr[i])) {
maxHeap.add(arr[i]);
} else {
maxHeap.add(arr[i]);
}
}
minHeap_size = minHeap.size();
maxHeap_size = maxHeap.size();
if (minHeap_size > maxHeap_size) {
System.out.println(minHeap.peek());
} else if (minHeap_size < maxHeap_size) {
System.out.println(maxHeap.peek());
} else {
System.out.println((maxHeap.peek() + minHeap.peek()) / 2);
}
}
}
public int[] frequentElements(int[] arr, int k) {
HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
for (int element : arr) {
map.put(element, map.getOrDefault(element, 0) + 1);
}
PriorityQueue<Integer> pq = new PriorityQueue<Integer>((a, b) -> map.get(b) - map.get(a));
pq.addAll(map.keySet());
int[] output = new int[k];
int i = 0;
while (i < k) {
output[i] = pq.poll();
i++;
}
return output;
}
public long minSumSquareDiff(int[] nums1, int[] nums2, int k1, int k2) {
PriorityQueue<Integer> difference = new PriorityQueue<Integer>((a, b) -> b - a);
for (int i = 0; i < nums1.length; i++) {
difference.add(Math.abs(nums1[i] - nums2[i]));
}
while (k1 != 0) {
if (difference.peek() == 0)
break;
int value = difference.poll() - 1;
difference.add(value);
k1--;
}
while (k2 != 0) {
if (difference.peek() == 0)
break;
int value = difference.poll() - 1;
difference.add(value);
k2--;
}
Long sum = 0L;
while (!difference.isEmpty()) {
int value = difference.poll();
sum = Math.multiplyFull(value, value) + sum;
}
return sum;
}
public List<List<Integer>> kSmallestPairs(int[] nums1, int[] nums2, int k) {
ArrayList<int[]> alist = new ArrayList<int[]>();
for(int i = 0; i< nums1.length; i++){
for(int j = 0; j< nums2.length; j++){
int[] arr = {nums1[i] , nums2[j]};
alist.add(arr);
}
}
PriorityQueue<int[]> pq = new PriorityQueue<int[]>((arr1, arr2) -> {
int sum1 = Arrays.stream(arr1).sum();
int sum2 = Arrays.stream(arr2).sum();
return Integer.compare(sum1, sum2);
});
pq.addAll(alist);
List<List<Integer>> list = new ArrayList<List<Integer>>();
while(k != 0){
int[] arr = pq.remove();
list.add(Arrays.stream(arr).boxed().collect(Collectors.toList()));
k--;
}
return list;
}
}