OD新A卷双机位- 热点网站统计(Java & JS & Python)

题目描述

企业路由器的统计页面,有一个功能需要动态统计公司访问最多的网页URL top N。请设计一个算法,可以高效动态统计Top N的页面。

 

输入描述

每一行都是一个URL或一个数字,如果是URL,代表一段时间内的网页访问;
如果是一个数字N,代表本次需要输出的Top N个URL。

输入约束:

1、总访问网页数量小于5000个,单网页访问次数小于65535次;
2、网页URL仅由字母,数字和点分隔符组成,且长度小于等于127字节;
3、数字是正整数,小于等于10且小于当前总访问网页数;

 

输出描述

每行输入要对应一行输出,输出按访问次数排序的前N个URL,用逗号分隔。

输出要求:

1、每次输出要统计之前所有输入,不仅是本次输入;
2、如果有访问次数相等的URL,按URL的字符串字典序升序排列,输出排序靠前的URL;

 

用例

输入 news.qq.com
news.sina.com.cn
news.qq.com
news.qq.com
game.163.com
game.163.com
www.huawei.com
www.cctv.com
3
www.huawei.com
www.cctv.com
www.huawei.com
www.cctv.com
www.huawei.com
www.cctv.com
www.huawei.com
www.cctv.com
www.huawei.com
3
输出 news.qq.com,game.163.com,news.sina.com.cn
www.huawei.com,www.cctv.com,news.qq.com
说明
输入 news.qq.com
www.cctv.com
1
www.huawei.com
www.huawei.com
2
3
输出 news.qq.com
www.huawei.com,news.qq.com
www.huawei.com,news.qq.com,www.cctv.com
说明

题目解析

本题需要注意:“每次输出要统计之前所有输入,不仅是本次输入”。

这句话,可以看第一个用例的第二行输出,其中news.qq.com的输出就取决于上面这句话。

 

另外,还有这句话:“总访问网页数量小于5000个,单网页访问次数小于65535次;”

也就说,最多有不超过5000 * 65535条访问URL记录,这个规模,我们需要尽可能地优化代码时间复杂度到O(1)左右,特别是“每次输出要统计之前所有输入,不仅是本次输入”,我们最好创建缓存表,而不是重新统计。

 

 


 

 

JS算法源码

const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;

void (async function () {
  const cache = {};

  while (true) {
    const line = await readline();

    if (/^\d+$/.test(line)) {
      console.log(sortURL(parseInt(line)));
    } else {
      cache[line] ? cache[line]++ : (cache[line] = 1);
    }
  }

  function sortURL(n) {
    return Object.entries(cache)
      .sort((a, b) => {
        // entry[0]代表key,即url
        // entry[1]代表val, 即出现次数count
        const res = b[1] - a[1];
        return res == 0 ? (a[0] > b[0] ? 1 : -1) : res;
      })
      .slice(0, n)
      .map((entry) => entry[0])
      .join(",");
  }
})();

 

Java算法源码

import java.util.HashMap;
import java.util.Objects;
import java.util.Scanner;
import java.util.StringJoiner;
import java.util.regex.Pattern;

public class Main {
  // 改正则用于判断一个字符串是否为正整数
  static Pattern reg = Pattern.compile("^\\d+$");

  // cache记录每个url出现次数
  static HashMap<String, Integer> cache = new HashMap<>();

  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);

    while (sc.hasNextLine()) {
      String tmp = sc.nextLine();

      if (reg.matcher(tmp).find()) {
        // 如果输入的是正整数
        System.out.println(sortURL(Integer.parseInt(tmp)));
      } else {
        // 输入的是url
        cache.put(tmp, cache.getOrDefault(tmp, 0) + 1);
      }
    }
  }

  public static String sortURL(int n) {
    StringJoiner sj = new StringJoiner(",");

    cache.entrySet().stream()
        .sorted(
            (a, b) ->
                Objects.equals(a.getValue(), b.getValue())
                    ? a.getKey().compareTo(b.getKey())
                    : b.getValue() - a.getValue())
        .limit(n)
        .map(ele -> ele.getKey())
        .forEach(url -> sj.add(url));

    return sj.toString();
  }
}

 

Python算法源码

# 输入获取
cache = {}  # 记录每个url出现的次数
ans = []  # 记录题解


def sortURL(n):
    urlCount = list(cache.items())
    urlCount.sort(key=lambda x: (-x[1], x[0]))

    return ",".join(map(lambda x: x[0], urlCount[:n]))


while True:
    tmp = input()

    if tmp.isnumeric():  # 如果输入的是数字,则需要对前面输入的url进行排序统计
        print(sortURL(int(tmp)))
    else:
        if cache.get(tmp) is None:
            cache[tmp] = 1
        else:
            cache[tmp] += 1

 

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐