【华为OD题库-101】查找舆情热词-java

题目

网上新闻越来越多,希望对新闻进行热词处理并归类,方便获取信息,现在已经将每篇文章处理为2个字符串,即一个标题,一个正文串,字符串中使用" “作为分隔符进行分词。
M篇新闻按照新闻发布的先后顺序处理完并输入,现在希望对所有新闻中出现的词语进行处理,输出出现频率最高的topN个词语,作为热词。标题中出现的词语频率系数为3,正文中出现的词语频率系数为1;返回的答案按照词语出现频率由高到低排序,当词语出现的频率相同时,在标题中出现的频率次数高的排在前面;如果仍然相同,则按照词语在标题中出现的先后顺序进行排序,先出现的排在前面;如果仍然相同,则按照词语在正文中出现的先后顺序进行排序,先出现的排在前面。
输入描述
第一行输入为正整数topN和文章数M,即要输出的出现频率最高的词语的个数和处理文章的数量,由于每篇文章被处理为标题和正文2行,因此后面有2*M行数据。
从第二行起,是按顺序处理后每篇文章的标题串和正文串,即第二行是第一篇文章的标题串,第三行是第一篇文章的正文串,第四行是第二篇文章的标题串,第五行是第二篇文章的正文串,以此类推。
参数限制如下:
0 < topN < 1000
0<M< 100000
0<每篇文章的词语数<5000
输出描述
使用一行输出出现频率最高的topN个词语,每个词语以” "隔开。
示例一:
输入
3 2
xinguan feiyan xinzeng bendi quezhen anli
ju baodao chengdu xinzeng xinguan feiyan bendi quezhen anli yili shenzhen xinzeng bendi quezhen anli liangli yiqing zhhengti kongzhi lianghao
xinguan yimiao linchuang shiyan
wuzhong xinguan yimiao tongguo sanqi linchuang shiyan xiaoguo lianghao
输出
xinguan xinzeng bendi
解释:
各词语出现频率:
xinguan=2*3+2=8
feiyan=1*3+1=4
xinzeng=1*3+2=5
bendi=1*3+2=5
quezhen=1*3+2=5
anli=1*3+2=5
yimiao=1*3+1=4
linchuang=1*3+1=4
shiyan=1*3+1=4
返回频率最高的三个词语,有4个词语出现频率都为5,标题出现频率都为3,所以选择先出现的两个词语xinzeng和bendi

思路

把排序需要的信息存下来,自定义排序即可

题解

package hwod;

import java.util.*;

public class HotWord {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int[] firstLines = Arrays.stream(sc.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();
        int topN = firstLines[0], m = firstLines[1];
        String[][] content = new String[m][2];
        for (int i = 0; i < m; i++) {
            content[i][0] = sc.nextLine();
            content[i][1] = sc.nextLine();
        }
        String[] res = hotWord(content, topN);
        for (int i = 0; i < res.length; i++) {
            if (i != 0) System.out.print(" ");
            System.out.print(res[i]);
        }
    }

    private static String[] hotWord(String[][] content, int topN) {
        //int[]中存放总次数,标题中次数,标题中顺序,正文中顺序
        Map<String, int[]> wordsMap = new HashMap<>();
        for (int i = 0; i < content.length; i++) {
            //标题
            int titleIdx = 0;
            int contentIdx = 0;
            for (String w : content[i][0].split(" ")) {
                titleIdx++;
                if (wordsMap.containsKey(w)) {
                    int[] originData = wordsMap.get(w);
                    originData[0] += 3;
                    originData[1]++;
                    //w出现过,不代表其titleIdx一定有值(有可能是作为正文出现过),所以此处需要更新titleidx的值
                    if (originData[2] == -1) originData[2] = titleIdx;
                    wordsMap.put(w, originData);
                } else {
                    wordsMap.put(w, new int[]{3, 1, titleIdx, -1});
                }
            }
            //正文
            for (String w : content[i][1].split(" ")) {
                contentIdx++;
                if (wordsMap.containsKey(w)) {
                    int[] originData = wordsMap.get(w);
                    originData[0] += 1;
                    if (originData[3] == -1) originData[3] = contentIdx;
                } else {
                    wordsMap.put(w, new int[]{1, 0, -1, contentIdx});
                }
            }
        }
        ArrayList<Map.Entry<String, int[]>> list = new ArrayList<>(wordsMap.entrySet());
        list.sort((o1, o2) -> {
            final int[] val1 = o1.getValue();
            final int[] val2 = o2.getValue();
            if (val1[0] != val2[0]) return val2[0] - val1[0];
            if (val1[1] != val2[1]) return val2[1] - val1[1];
            if (val1[2] != val2[2]) return val1[2] - val2[2];
            return val1[3] - val2[3];
        });
        String[] res = new String[topN];
        for (int i = 0; i < topN; i++) {
            res[i] = list.get(i).getKey();
        }
        return res;
    }

}

推荐

如果你对本系列的其他题目感兴趣,可以参考华为OD机试真题及题解(JAVA),查看当前专栏更新的所有题目。

说明

本专栏所有文章均为原创,欢迎转载,请注明文章出处:https://blog.csdn.net/qq_31076523/article/details/134176793。百度和各类采集站皆不可信,搜索请谨慎鉴别。技术类文章一般都有时效性,本人习惯不定期对自己的博文进行修正和更新,因此请访问出处以查看本文的最新版本。

  • 20
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值