题目描述
企业路由器的统计页面,有一个功能需要动态统计公司访问最多的网页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)左右,特别是“每次输出要统计之前所有输入,不仅是本次输入”,我们最好创建缓存表,而不是重新统计。
其余地就感觉没什么需要注意的了,都是逻辑实现了。
2023.08.28
根据考友反馈,本题输入截止条件不能使用空行判断,可以直接死循环获取
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
免责声明:
1、IT资源小站为非营利性网站,全站所有资料仅供网友个人学习使用,禁止商用
2、本站所有文档、视频、书籍等资料均由网友分享,本站只负责收集不承担任何技术及版权问题
3、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除下载链接并致以最深的歉意
4、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责
5、一经注册为本站会员,一律视为同意网站规定,本站管理员及版主有权禁止违规用户
6、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和IT资源小站的同意
7、IT资源小站管理员和版主有权不事先通知发贴者而删除本文
评论0