提交 364b1733 编写于 作者: GreyZeng's avatar GreyZeng

update heap greater

上级 96b0a0e9
......@@ -85,6 +85,10 @@
- 连接点算重合区域
- 连接点不算重合区域
[加强堆结构说明](https://www.cnblogs.com/greyzeng/p/16936506.html)
[使用加强堆解决 topK 问题](https://www.cnblogs.com/greyzeng/p/16125150.html)
## 更多
[算法和数据结构学习笔记:CSDN](https://blog.csdn.net/hotonyhui/category_1250716.html)
......
......@@ -5,6 +5,9 @@ import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
/**
* @since 21
*/
// TODO
// 给定一个整型数组,int[] arr;和一个布尔类型数组,boolean[] op
// 两个数组一定等长,假设长度为N,arr[i]表示客户编号,op[i]表示客户操作
......@@ -51,7 +54,7 @@ import java.util.List;
// 会再次根据之前规则回到某个区域中,进入区域的时间重记
// 请遍历arr数组和op数组,遍历每一步输出一个得奖名单
// public List<List<Integer>> topK (int[] arr, boolean[] op, int k)
public class Code_EveryStepShowBoss {
public class EveryStepShowBoss {
public static List<List<Integer>> topK(int[] arr, boolean[] op, int k) {
List<List<Integer>> ans = new ArrayList<>();
......@@ -66,7 +69,7 @@ public class Code_EveryStepShowBoss {
// 干完所有的事,模拟,不优化
public static List<List<Integer>> compare(int[] arr, boolean[] op, int k) {
HashMap<Integer, Customer> map = new HashMap<>();
ArrayList<Customer> cands = new ArrayList<>();
ArrayList<Customer> cans = new ArrayList<>();
ArrayList<Customer> daddy = new ArrayList<>();
List<List<Integer>> ans = new ArrayList<>();
for (int i = 0; i < arr.length; i++) {
......@@ -81,7 +84,7 @@ public class Code_EveryStepShowBoss {
// 用户之前购买数>0, 此时买货
// 用户之前购买数>0, 此时退货
if (!map.containsKey(id)) {
map.put(id, new Customer(id, 0, 0));
map.put(id, new Customer(id, 0));
}
// 买、卖
Customer c = map.get(id);
......@@ -95,20 +98,20 @@ public class Code_EveryStepShowBoss {
}
// c
// 下面做
if (!cands.contains(c) && !daddy.contains(c)) {
if (!cans.contains(c) && !daddy.contains(c)) {
if (daddy.size() < k) {
c.enterTime = i;
daddy.add(c);
} else {
c.enterTime = i;
cands.add(c);
cans.add(c);
}
}
cleanZeroBuy(cands);
cleanZeroBuy(cans);
cleanZeroBuy(daddy);
cands.sort(new CandidateComparator());
cans.sort(new CandidateComparator());
daddy.sort(new DaddyComparator());
move(cands, daddy, k, i);
move(cans, daddy, k, i);
ans.add(getCurAns(daddy));
}
return ans;
......@@ -120,16 +123,16 @@ public class Code_EveryStepShowBoss {
}
// 候选区不为空
if (daddy.size() < k) {
Customer c = cands.get(0);
Customer c = cands.getFirst();
c.enterTime = time;
daddy.add(c);
cands.remove(0);
cands.removeFirst();
} else { // 等奖区满了,候选区有东西
if (cands.get(0).buy > daddy.get(0).buy) {
Customer oldDaddy = daddy.get(0);
daddy.remove(0);
Customer newDaddy = cands.get(0);
cands.remove(0);
if (cands.getFirst().buy > daddy.getFirst().buy) {
Customer oldDaddy = daddy.getFirst();
daddy.removeFirst();
Customer newDaddy = cands.getFirst();
cands.removeFirst();
newDaddy.enterTime = time;
oldDaddy.enterTime = time;
daddy.add(newDaddy);
......@@ -139,16 +142,14 @@ public class Code_EveryStepShowBoss {
}
public static void cleanZeroBuy(ArrayList<Customer> arr) {
List<Customer> noZero = new ArrayList<Customer>();
List<Customer> noZero = new ArrayList<>();
for (Customer c : arr) {
if (c.buy != 0) {
noZero.add(c);
}
}
arr.clear();
for (Customer c : noZero) {
arr.add(c);
}
arr.addAll(noZero);
}
public static List<Integer> getCurAns(ArrayList<Customer> daddy) {
......@@ -166,7 +167,7 @@ public class Code_EveryStepShowBoss {
boolean[] op = new boolean[len];
for (int i = 0; i < len; i++) {
arr[i] = (int) (Math.random() * maxValue);
op[i] = Math.random() < 0.5 ? true : false;
op[i] = Math.random() < 0.5;
}
return new Data(arr, op);
}
......@@ -182,8 +183,8 @@ public class Code_EveryStepShowBoss {
if (cur1.size() != cur2.size()) {
return false;
}
cur1.sort((a, b) -> a - b);
cur2.sort((a, b) -> a - b);
cur1.sort(Comparator.comparingInt(a -> a));
cur2.sort(Comparator.comparingInt(a -> a));
for (int j = 0; j < cur1.size(); j++) {
if (!cur1.get(j).equals(cur2.get(j))) {
return false;
......@@ -225,7 +226,7 @@ public class Code_EveryStepShowBoss {
public int buy;
public int enterTime;
public Customer(int v, int b, int o) {
public Customer(int v, int b) {
id = v;
buy = b;
enterTime = 0;
......@@ -250,14 +251,14 @@ public class Code_EveryStepShowBoss {
public static class WhosYourDaddy {
private final int daddyLimit;
private HashMap<Integer, Customer> customers;
private Code_HeapGreater<Customer> candHeap;
private Code_HeapGreater<Customer> daddyHeap;
private final HashMap<Integer, Customer> customers;
private final HeapGreater<Customer> candHeap;
private final HeapGreater<Customer> daddyHeap;
public WhosYourDaddy(int limit) {
customers = new HashMap<>();
candHeap = new Code_HeapGreater<>(new CandidateComparator());
daddyHeap = new Code_HeapGreater<>(new DaddyComparator());
candHeap = new HeapGreater<>(new CandidateComparator());
daddyHeap = new HeapGreater<>(new DaddyComparator());
daddyLimit = limit;
}
......@@ -267,7 +268,7 @@ public class Code_EveryStepShowBoss {
return;
}
if (!customers.containsKey(id)) {
customers.put(id, new Customer(id, 0, 0));
customers.put(id, new Customer(id, 0));
}
Customer c = customers.get(id);
if (buyOrRefund) {
......
......@@ -5,16 +5,20 @@ import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
/**
* @param <T>
* @since 21
*/
// 加强堆
// 笔记:https://www.cnblogs.com/greyzeng/p/16936506.html
public class Code_HeapGreater<T> {
public class HeapGreater<T> {
private ArrayList<T> heap;
private HashMap<T, Integer> indexMap; // 元素在堆中的位置
private final ArrayList<T> heap;
private final HashMap<T, Integer> indexMap; // 元素在堆中的位置
private int heapSize; // 和heap配合使用
private Comparator<? super T> comp;
private final Comparator<? super T> comp;
public Code_HeapGreater(Comparator<T> c) {
public HeapGreater(Comparator<T> c) {
heap = new ArrayList<>();
indexMap = new HashMap<>();
comp = c;
......@@ -33,7 +37,10 @@ public class Code_HeapGreater<T> {
}
public T peek() {
return heap.get(0);
// since jdk 21
// before jdk 21 use
// heap.get(0)
return heap.getFirst();
}
public void push(T obj) {
......@@ -43,7 +50,10 @@ public class Code_HeapGreater<T> {
}
public T pop() {
T ans = heap.get(0);
// since jdk 21
// before jdk 21 use
// heap.get(0)
T ans = heap.getFirst();
swap(0, heapSize - 1);
indexMap.remove(ans);
heap.remove(--heapSize);
......@@ -52,11 +62,14 @@ public class Code_HeapGreater<T> {
}
public void remove(T obj) {
// 用最后一个元素去顶替要删掉的元素
T replace = heap.get(heapSize - 1);
// 要删掉的元素
int index = indexMap.get(obj);
indexMap.remove(obj);
heap.remove(--heapSize);
if (obj != replace) { // obj == replace表示删掉的是最后一个位置的数据,此时不需要进行resign操作
// 用顶替的元素去填充被删的元素位置
heap.set(index, replace);
indexMap.put(replace, index);
resign(replace);
......@@ -70,11 +83,7 @@ public class Code_HeapGreater<T> {
// 请返回堆上的所有元素
public List<T> getAllElements() {
List<T> ans = new ArrayList<>();
for (T c : heap) {
ans.add(c);
}
return ans;
return new ArrayList<>(heap);
}
private void heapInsert(int index) {
......
......@@ -8,7 +8,7 @@ package git.snippet.heap;
// 3. 把堆的大小减小成0之后,排序完成
// 堆排序额外空间复杂度O(1)
// 测评:https://www.lintcode.com/problem/464
public class Code_HeapSort {
public class HeapSort {
public static void sort(int[] arr) {
if (null == arr || arr.length < 2) {
return;
......
package git.snippet.heap;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
@DisplayName("加强堆结构测试")
public class Code_HeapGreaterTest {
// 加强堆测试
@Test
@DisplayName("加强堆结构测试")
public void testGreaterHeap() {
int value = 1000;
int limit = 100;
int testTimes = 1000000;
for (int i = 0; i < testTimes; i++) {
int curLimit = (int) (Math.random() * limit) + 1;
Code_HeapGreater<Integer> my =
new Code_HeapGreater<>(
(o1, o2) -> o2 - o1);
RightMaxHeap test = new RightMaxHeap(curLimit);
int curOpTimes = (int) (Math.random() * limit);
for (int j = 0; j < curOpTimes; j++) {
if (test.isEmpty()) {
int curValue = (int) (Math.random() * value);
my.push(curValue);
test.push(curValue);
} else if (test.isFull()) {
if (my.pop() != test.pop()) {
Assertions.fail();
}
} else {
if (Math.random() < 0.5) {
int curValue = (int) (Math.random() * value);
my.push(curValue);
test.push(curValue);
} else {
if (my.pop() != test.pop()) {
Assertions.fail();
}
}
}
}
}
}
}
\ No newline at end of file
package git.snippet.heap;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import static git.snippet.common.Generator.copyArray;
import static git.snippet.common.Generator.generateRandomArray;
@DisplayName("堆排序")
public class Code_HeapSortTest {
@Test
@DisplayName("堆排序测试")
public void heapSortTest() {
int times = 500000; // 测试的次数
int maxSize = 100; // 数组的最大长度是100
int maxValue = 100; // 数组元素的大小[-100,100]
for (int i = 0; i < times; i++) {
int[] arr1 = generateRandomArray(maxSize, maxValue);
int[] arr4 = copyArray(arr1);
Code_HeapSort.sort(arr1);
Arrays.sort(arr4);
Assertions.assertArrayEquals(arr1, arr4);
}
}
}
\ No newline at end of file
......@@ -4,40 +4,63 @@ import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.Objects;
import java.util.PriorityQueue;
import static git.snippet.common.Generator.copyArray;
import static git.snippet.common.Generator.generateRandomArray;
@DisplayName("堆结构测试")
public class MaxHeapTest {
public class HeapTest {
@Test
@DisplayName("堆排序测试")
public void heapSortTest() {
int times = 500000; // 测试的次数
int maxSize = 100; // 数组的最大长度是100
int maxValue = 100; // 数组元素的大小[-100,100]
for (int i = 0; i < times; i++) {
int[] arr1 = generateRandomArray(maxSize, maxValue);
int[] arr4 = copyArray(arr1);
HeapSort.sort(arr1);
Arrays.sort(arr4);
Assertions.assertArrayEquals(arr1, arr4);
}
}
@Test
@DisplayName("大根堆测试")
public void testHeap() {
int value = 1000;
int value = 10000;
int limit = 100;
int testTimes = 1000000;
int testTimes = 2000000;
for (int i = 0; i < testTimes; i++) {
int curLimit = (int) (Math.random() * limit) + 1;
MaxHeap my = new MaxHeap(curLimit);
RightMaxHeap test = new RightMaxHeap(curLimit);
PriorityQueue<Integer> test = new PriorityQueue<>((o1, o2) -> o2 - o1);
int curOpTimes = (int) (Math.random() * limit);
for (int j = 0; j < curOpTimes; j++) {
if (my.isEmpty() != test.isEmpty()) {
Assertions.fail();
}
if (my.isFull() != test.isFull()) {
if (my.isFull() != (test.size() == curLimit)) {
Assertions.fail();
}
if (my.isEmpty()) {
int curValue = (int) (Math.random() * value);
my.push(curValue);
test.push(curValue);
test.add(curValue);
} else if (my.isFull()) {
if (my.pop() != test.pop()) {
if (!Objects.equals(my.pop(), test.poll())) {
Assertions.fail();
}
} else {
if (Math.random() < 0.5) {
int curValue = (int) (Math.random() * value);
my.push(curValue);
test.push(curValue);
test.add(curValue);
} else {
if (my.pop() != test.pop()) {
if (!Objects.equals(my.pop(), test.poll())) {
Assertions.fail();
}
}
......@@ -46,5 +69,39 @@ public class MaxHeapTest {
}
}
@Test
@DisplayName("加强堆测试")
public void testGreaterHeap() {
int value = 1000;
int limit = 100;
int testTimes = 2000000;
for (int i = 0; i < testTimes; i++) {
int curLimit = (int) (Math.random() * limit) + 1;
HeapGreater<Integer> myHeap = new HeapGreater<>((o1, o2) -> o2 - o1);
PriorityQueue<Integer> rightHeap = new PriorityQueue<>((o1, o2) -> o2 - o1);
int curOpTimes = (int) (Math.random() * limit);
for (int j = 0; j < curOpTimes; j++) {
if (rightHeap.isEmpty()) {
int curValue = (int) (Math.random() * value);
myHeap.push(curValue);
rightHeap.add(curValue);
} else if (rightHeap.size() == curLimit) {
if (!Objects.equals(myHeap.pop(), rightHeap.poll())) {
Assertions.fail();
}
} else {
if (Math.random() < 0.5) {
int curValue = (int) (Math.random() * value);
myHeap.push(curValue);
rightHeap.add(curValue);
} else {
if (!Objects.equals(myHeap.pop(), rightHeap.poll())) {
Assertions.fail();
}
}
}
}
}
}
}
\ No newline at end of file
package git.snippet.heap;
public class RightMaxHeap {
private final int limit;
private int[] arr;
private int size;
public RightMaxHeap(int limit) {
arr = new int[limit];
this.limit = limit;
size = 0;
}
public boolean isEmpty() {
return size == 0;
}
public boolean isFull() {
return size == limit;
}
public void push(int value) {
if (size == limit) {
throw new RuntimeException("heap is full");
}
arr[size++] = value;
}
public int pop() {
int maxIndex = 0;
for (int i = 1; i < size; i++) {
if (arr[i] > arr[maxIndex]) {
maxIndex = i;
}
}
int ans = arr[maxIndex];
arr[maxIndex] = arr[--size];
return ans;
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册