需求
用户数量:200000000
用户最大积分:1000000
随机用户的分数,查找该用户的排名
思路
模拟用户数量,采用树形结构形式,记录区间数量
node 节点代码:
@Setter @Getter public class Node { // 该分数区间范围的多少人 public int total = 0; // 区间开始 public int start = 0; // 区间结束 public int end = 0; // 子节点 public Map<String, Node> subNode; @Override public String toString() { return JSON.toJSONString(this); } } |
主代码中生成数据结构,并且随机生成分数,查询该分数排名
public class ConMain { public static ConcurrentMap<String, Node> data = new ConcurrentHashMap<String, Node>(); public static int THOUND = 1000; public final static long TOTAL = 200000000; public final static long RANDOMMARK = 1000000; public static volatile int totalThread = 0; public static void main(String[] args) throws InterruptedException { long start = System.currentTimeMillis(); ExecutorService fixedThread = Executors.newFixedThreadPool(4); int split = (int) (TOTAL / THOUND); for (long index = 0; index < split; index++) { fixedThread.execute(new Process()); totalThread++; } while (totalThread > 0) { Thread.sleep(1000l); } fixedThread.shutdown(); long end = System.currentTimeMillis(); System.out.println(end - start); start = end; findTen(); end = System.currentTimeMillis(); System.out.println(end - start); } public static class Process implements Runnable { @Override public void run() { for (long index = 0; index < THOUND; index++) { int mark = (int) (Math.random() * RANDOMMARK); run(mark); } // System.out.println(Thread.currentThread().getName() + "完成!"); totalThread--; } public void run(int mark) { int start = (int) (mark / THOUND) * THOUND; int end = ((int) (mark / THOUND) + 1) * THOUND; String key = start + "-" + end; Node node = null; if (data.containsKey(key)) { node = data.get(key); } else { node = new Node(); node.setStart(start); node.setEnd(end); data.put(key, node); } node.setTotal(node.getTotal() + 1); int point = mark % THOUND; key = point + "-" + point; Node node1 = new Node(); if (node.getSubNode() == null) { node.setSubNode(new HashMap<String, Node>()); } if (node.getSubNode().containsKey(key)) { node1 = node.getSubNode().get(key); } else { node1 = new Node(); node1.setStart(start); node1.setEnd(end); node.getSubNode().put(key, node1); } node1.setEnd(point); node1.setStart(point); // node1.setName(name); node1.setTotal(node1.getTotal() + 1); } } private static void findTen() { for (long index = 0; index < 10; index++) { int mark = (int) (Math.random() * RANDOMMARK); int start = (int) (mark / THOUND) * THOUND; int end = ((int) (mark / THOUND) + 1) * THOUND; String key = start + "-" + end; if (data.containsKey(key)) { Node node = data.get(key); int point = mark % THOUND; key = point + "-" + point; if (node.getSubNode().containsKey(key)) { Node node1 = node.getSubNode().get(key); // 该分数下的用户数量 int markTotal = node1.getTotal(); // 计算该区域下该分数前面有多少人 for (; point <= THOUND; point++) { key = point + "-" + point; if (node.getSubNode().containsKey(key)) { Node node2 = node.getSubNode().get(key); markTotal += node2.getTotal(); } } // 计算该区域前面有多少人 for (; end <= TOTAL; start = end) { end += THOUND; key = start + "-" + end; if (data.containsKey(key)) { node = data.get(key); markTotal += node.getTotal(); } } System.out.println("分数为:" + mark + "的用户,其排名为:!" + markTotal); } else { System.out.println("分数为:" + mark + " 用户不存在!"); } } else { System.out.println("分数为:" + mark + " 用户不存在!"); } } } } |