实时输出topk最频繁变动的股价
网上看到了一道关于bloomburg的面试题,follow 评论的思路 自己试着写了一个HashHeap的实现。
基本思路是维护一个大小为K的最小堆,里面是topK股价变动的公司ID(假设ID是Integer)
HashHeap中维护一个companyIdHeap 之外还有一个HashMap 它的key 是CompanyId, value是Company信息 此处我假设company信息包含这个company在companyIdHeap中的index (这个index可以使delete function的复杂度降到O(logK))和它的股价变化了多少次
每当有新的估价更新,假设应用会调用HashHeap的add函数 输入是当前股价变化的公司ID 然后更新 hashmap 和 根据当前heap size更新companyIdHeap
在更新companyIdHeap的时候 如果这个变化的公司的股价变化次数大于最小堆的root 那么替换掉这个root 然后从0向下调整heap heap调整的比较条件是看谁的股价变化次数少
delete函数直接delete掉一个company O(logK)
poll函数是给heap root的company的股价变化次数减一(其实还没想好这个函数具体应该做什么 暂时把它放在注释里面)
不足之处请指出! 多谢!
1 package Heap; 2 3 import java.util.*; 4 5 public class HashHeap { 6 //a list of companyId 7 private List<Integer> companyIdHeap; 8 private int size_t; 9 //map from companyId to Node {index in heap and frequent} 10 private Map<Integer, Node> companyToFrequent; 11 private String mode; //min or max 12 private int K; 13 class Node{ 14 public int index; 15 public int frequent; 16 public Node (int index, int fre){ 17 this.index= index; 18 this.frequent = fre; 19 } 20 public Node(Node node){ 21 this.index = node.index; 22 this.frequent = node.frequent; 23 } 24 } 25 26 public HashHeap(int K){ 27 this.companyIdHeap = new ArrayList<Integer>(); 28 this.size_t =0; 29 this.companyToFrequent = new HashMap<Integer, Node>(); 30 mode = "min"; 31 this.K = K; 32 } 33 34 public int peek(){ 35 if(!companyIdHeap.isEmpty()) 36 return companyIdHeap.get(0); 37 return -1; 38 } 39 40 public int size(){ 41 return size_t; 42 } 43 44 public boolean empty(){ 45 return companyIdHeap.size()==0; 46 } 47 48 public int parent(int id){ 49 if(id==0){ 50 return -1; 51 } 52 return (id-1)/2; 53 } 54 55 public int lson(int id){ 56 return 2*id +1; 57 } 58 59 public int rson(int id){ 60 return 2*id+2; 61 } 62 63 public boolean compare(int companyA, int companyB){ 64 if(companyToFrequent.get(companyA).frequent<companyToFrequent.get(companyB).frequent){ 65 if(mode.equals("min")){ 66 return true; 67 }else{ 68 return false; 69 } 70 }else{ 71 if(mode.equals("min")){ 72 return false; 73 }else{ 74 return true; 75 } 76 } 77 } 78 79 public void swap(int indexA, int indexB){ 80 int companyA = companyIdHeap.get(indexA); 81 int companyB = companyIdHeap.get(indexB); 82 Node compNodeA = companyToFrequent.get(companyA); 83 Node compNodeB = companyToFrequent.get(companyB); 84 companyIdHeap.set(indexA, companyB); 85 companyIdHeap.set(indexB, companyA); 86 companyToFrequent.put(companyA, new Node(indexB, compNodeA.frequent)); 87 companyToFrequent.put(companyB, new Node(indexA, compNodeB.frequent)); 88 } 89 90 public void siftup(int index){ 91 while(parent(index)>-1){ 92 int parent = parent(index); 93 if(compare(companyIdHeap.get(parent), companyIdHeap.get(index))){ 94 break; 95 }else{ 96 swap(parent, index); 97 } 98 index = parent; 99 } 100 } 101 102 public void siftdown(int index){ 103 while(lson(index)< companyIdHeap.size()){ 104 int leftSon = lson(index); 105 int rightSon = rson(index); 106 int son = rightSon; 107 if(rightSon>=companyIdHeap.size()||compare(companyIdHeap.get(leftSon),companyIdHeap.get(rightSon))){ 108 son = leftSon; 109 } 110 if(compare(companyIdHeap.get(index), companyIdHeap.get(son))){ 111 break; 112 }else{ 113 swap(index, son); 114 } 115 index=son; 116 } 117 118 } 119 120 public void add(int company){ 121 //update hashmap 122 if(companyToFrequent.containsKey(company)){ 123 Node node = companyToFrequent.get(company); 124 companyToFrequent.put(company, new Node(node.index, node.frequent+1)); 125 }else{ 126 companyToFrequent.put(company, new Node(-1, 1)); 127 } 128 //update heap 129 Node node = companyToFrequent.get(company); 130 if(this.size_t==K){ 131 //if heap need to be updated 132 if(compare(peek(), company)){ 133 companyIdHeap.set(0, company); 134 companyToFrequent.put(company, new Node(0, node.frequent)); 135 siftdown(0); 136 } 137 return; 138 } 139 companyIdHeap.add(company); 140 size_t++; 141 companyToFrequent.put(company, new Node(companyIdHeap.size()-1, node.frequent)); 142 siftup(companyIdHeap.size()-1); 143 } 144 145 public void delete(int company){ 146 if(companyToFrequent.containsKey(company)){ 147 Node node = companyToFrequent.get(company); 148 int index = node.index; 149 swap(index, companyIdHeap.size()-1); 150 companyIdHeap.remove(companyIdHeap.size()-1); 151 companyToFrequent.remove(company); 152 size_t--; 153 //the condition will be false if index == companyIdHeap.size()-1 before 154 if(index<companyIdHeap.size()){ 155 siftup(index); 156 siftdown(index); 157 } 158 } 159 } 160 161 /*public int poll(){ 162 int res = companyIdHeap.get(0); 163 Node node = companyToFrequent.get(res); 164 if(node.frequent==1){ 165 size_t--; 166 swap(0, companyIdHeap.size()-1); 167 companyIdHeap.remove(companyIdHeap.size()-1); 168 companyToFrequent.remove(res); 169 // the condition will be true is companyIdHeap.size() == 1 before 170 if(companyIdHeap.size()>0){ 171 siftdown(0); 172 } 173 }else{ 174 companyToFrequent.put(res, new Node(0, node.frequent-1)); 175 } 176 177 return res; 178 }*/ 179 }