【华为OD-E卷 - 热点网站统计 100分(python、java、c++、js、c)】
题目
企业路由器的统计页面,有一个功能需要动态统计公司访问最多的网页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
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
输出:
news.qq.com,game.163.com,news.sina.com.cn
www.huawei.com,www.cctv.com,news.qq.com
- 1
- 2
用例二:
输入:
news.qq.com
www.cctv.com
1
www.huawei.com
www.huawei.com
2
3
- 1
- 2
- 3
- 4
- 5
- 6
- 7
输出:
news.qq.com
www.huawei.com,news.qq.com
www.huawei.com,news.qq.com,www.cctv.com
- 1
- 2
- 3
python解法
- 解题思路:
- 这段代码实现了一个URL统计排序程序,核心目标是:
统计输入中每个URL的出现次数。
当输入一个数字 n 时,输出前 n 个出现次数最多的URL,按以下规则排序:
优先按出现次数降序排序;
若出现次数相同,按URL的字典序升序排序。
程序接收用户输入直到EOF,每行输入可能是URL或数字。
具体步骤如下:
使用 defaultdict 记录每个URL的出现次数。
当输入是数字时,根据统计结果对URL进行排序,并获取前 n 个URL。
程序处理完所有输入后,输出结果。
from collections import defaultdict
# 使用 defaultdict 存储每个 URL 的统计次数
cache = defaultdict(int)
# 用于存储所有需要输出的结果
output = []
def process_input(line):
"""
处理一行输入,如果是数字则输出前 n 个 URL,若为 URL 则更新统计信息。
"""
if line.isdigit():
# 如果输入为数字,解析为 n
n = int(line)
# 对缓存中的 URL 按规则排序
sorted_urls = sorted(cache.items(), key=lambda x: (-x[1], x[0]))
# 获取前 n 个 URL,按照逗号拼接为字符串
result = ",".join(url for url, count in sorted_urls[:n])
# 将结果保存到输出列表中
output.append(result)
else:
# 如果输入为 URL,则更新其统计次数
cache[line] += 1
# 循环读取输入,直到 EOF(End of File)
while True:
try:
# 读取并去除首尾空格
line = input().strip()
if not line:
break
# 处理输入
process_input(line)
except EOFError:
# 捕获 EOF 错误并退出循环
break
# 输出所有结果
for line in output:
print(line)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
java解法
- 解题思路
- 该代码实现了一个URL统计和排序功能。核心目标是:
统计输入中每个URL的出现次数:
使用 TreeMap 存储URL及其出现次数,保证按字典序自动排序。
处理用户输入:
如果输入为数字 n,输出前 n 个出现次数最多的URL。
如果输入为URL,更新URL的统计次数。
排序规则:
出现次数按降序排序。
若出现次数相同,按字典序升序排序。
优先队列实现排序:
使用 PriorityQueue 实现排序,以满足自定义排序规则。
程序通过不断接收输入处理数据,直到输入结束
import java.util.*;
public class Main {
// 使用 TreeMap 存储 URL 和其统计次数,按字典序自动排序
static Map<String, Integer> urlCount = new TreeMap<>();
// 优先队列,用于按规则排序输出前 n 个 URL
static PriorityQueue<Map.Entry<String, Integer>> pq;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// 持续接收输入,直到没有更多输入(EOF)
while (sc.hasNextLine()) {
String input = sc.nextLine();
// 判断输入是否为数字
if (isNumeric(input)) {
// 输入为数字,解析为 n,并输出前 n 个 URL
int n = Integer.parseInt(input);
System.out.println(getTopN(n));
} else {
// 输入为 URL,更新其统计次数
urlCount.put(input, urlCount.getOrDefault(input, 0) + 1);
}
}
}
/**
* 获取出现次数最多的前 n 个 URL,按规则排序
* @param n 要输出的 URL 个数
* @return 按规则排序的前 n 个 URL,逗号分隔
*/
private static String getTopN(int n) {
// 初始化优先队列,按规则排序:
// 1. 出现次数降序;
// 2. 出现次数相同时,按字典序升序。
pq = new PriorityQueue<>((a, b) -> {
if (!a.getValue().equals(b.getValue())) {
return b.getValue() - a.getValue(); // 出现次数降序
} else {
return a.getKey().compareTo(b.getKey()); // 字典序升序
}
});
// 将所有 URL 的统计数据加入优先队列
pq.addAll(urlCount.entrySet());
// 使用 StringJoiner 拼接结果字符串
StringJoiner sj = new StringJoiner(",");
for (int i = 0; i < n && !pq.isEmpty(); i++) {
// 获取优先队列中当前出现次数最多的 URL
sj.add(pq.poll().getKey());
}
return sj.toString();
}
/**
* 判断输入字符串是否为数字
* @param str 输入字符串
* @return true 如果字符串是数字,否则返回 false
*/
private static boolean isNumeric(String str) {
try {
Integer.parseInt(str);
return true;
} catch (NumberFormatException e) {
return false;
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
C++解法
- 解题思路
更新中
- 1
C解法
更新中
- 1
JS解法
统计输入中每个 URL 的访问次数:
使用对象(urlVisits)记录 URL 的访问次数。
处理用户输入:
如果输入是一个数字 n,则输出访问次数最多的前 n 个 URL。
如果输入是一个 URL,则更新其访问次数。
排序规则:
访问次数按降序排序;
访问次数相同时,按字典序升序排序。
动态输入读取:
使用 readline 模块异步读取标准输入。
每次读取一行后判断输入类型并处理
const readline = require("readline").createInterface({ input: process.stdin }); // 创建 readline 接口,用于异步读取标准输入
const iterator = readline[Symbol.asyncIterator](); // 获取异步迭代器以逐行读取输入
const getInput = async () => (await iterator.next()).value; // 异步获取一行输入
(async function () {
const urlVisits = {}; // 使用对象存储 URL 及其访问次数,键为 URL,值为访问次数
while ((input = await getInput())) {
const number = parseInt(input); // 尝试将输入解析为数字
if (isNaN(number)) { // 如果输入不是数字
// 将输入视为 URL,更新其访问次数
urlVisits[input] = (urlVisits[input] ?? 0) + 1;
continue; // 跳过当前循环,继续读取下一个输入
}
// 如果输入是数字,获取访问次数最多的前 number 个 URL
const result = Object.entries(urlVisits) // 将 urlVisits 对象转为 [key, value] 的数组
.sort(
(first, second) =>
second[1] - first[1] || first[0].localeCompare(second[0]) // 按规则排序
)
.slice(0, number) // 截取前 number 个
.map((item) => item[0]) // 提取 URL
.join(","); // 将结果拼接为逗号分隔的字符串
console.log(result); // 输出结果
}
})();
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
注意:
如果发现代码有用例覆盖不到的情况,欢迎反馈!会在第一时间修正,更新。
解题不易,如对您有帮助,欢迎点赞/收藏
评论记录:
回复评论: