2亿用户积分最大1百中查找某个分数的排名

需求

    用户数量: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 + " 用户不存在!");
            }
        }
    }

}

 

转载于:https://my.oschina.net/tiger/blog/1814352

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值