首页 > 试题广场 >

小红书推荐算法

[编程题]小红书推荐算法
  • 热度指数:1018 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
我们假定一个用户搜索的关键词是他感兴趣的,现在请你基于这个前提设计一个小红书购物的推荐算法。
该算法的核心思想如下:首先给定一个商品清单,其中有每个商品所包含的关键词属性,然后给出用户最近搜索过的一些关键词,请你将包含用户搜索过的更多关键词的商品排在用户目录的前面。
对于包含关键词数量相同的商品,我们按默认顺序排序,也就是说按输入给定的顺序优先级。

输入描述:
第一行输入一个正整数n,q,代表商品数量、用户搜索的关键词数量。
第二行输入q个互不相同的、仅由小写字母组成的字符串,代表用户搜索过的关键词。
接下来的2*n行,每两行描述一个商品。
第一行输入一个仅由小写字母组成的字符串name和一个正整数m_i,代表商品的名称和商品包含的关键词属性数量。
第二行输入m_i个互不相同的、仅由小写字母组成的字符串,代表每个商品的属性。
1\leq n,q \leq 30000
所有的m_i之和不超过30000
保证所有字符串长度不超过 20。所有商品的名称互不相同。


输出描述:
输出n行,每行一个字符串,代表用户主页中显示的商品名称。
示例1

输入

2 5
red book game music sigma
mozart 3
book classic music
arcaea 4
red music game hard

输出

arcaea
mozart

说明

arcaea 这个商品包含了用户搜索的 3 个关键词,而 mozart 只包含了 2 个。

c++ 解法
无脑比较求解了,700ms, 4m, 好像比楼下的java还要慢很多。 不知道有没有 更快的办法。
另外 这个 题目输人好像莫名有空格,不知道咋回事

直接用unordered_set去查找这五个破玩意,太亏了,会超时,所以直接在输入的时候比较判断,总数达到标签输出上限就不管了。

至于要求按原有顺序输出的话,我在别的题目手动实现过了,首先把整体用快排排序, 然后内部遍历, 相同计数的用输入顺序字典进行快速 排序。

这里省事直接stablesort了。

#include <algorithm>
#include <iostream>
#include <string>
#include <unordered_set>
#include <vector>
using namespace std;

int main() {

    int n, q;
    cin >> n >> q;
    vector<string> keywords(q);
    for (auto& w : keywords) {
        cin >> w;
    }

    vector<pair<string, int>> ret(n);

    while (n--) {
        string name; // 商品名称
        int m;
          // 商品属性tag 也就是关键词

        cin >> name >> m;

        int count = 0;

        while (m--) {
            string s;
            cin >> s;

            if (count < q) {
                for (const auto& kw : keywords) {
                    if (s == kw) {
                        count++;
                        break;
                    }
                }
            } else {
                continue;
            }
        }
        ret.push_back(make_pair(name, count));
    }

    // 比较函数直接用lambda表达式了
    stable_sort(ret.begin(), ret.end(), [](const pair<string, int>& a,
    const pair<string, int>& b) {
        return a.second > b.second;
    } );

    for (const auto& p : ret) {

        if (p.first.size() == 0)
            continue;
        cout << p.first << endl;
    }

    return 0;
}
// 64 位输出请用 printf("%lld")
发表于 2025-03-27 15:08:22 回复(0)
import java.util.*; 

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 商品数量
        int itemCount = in.nextInt();
        // 关键词数量
        int wordCount = in.nextInt();
        // 用哈希集方便判断是否未关键词
        Set<String> set = new HashSet<>();
        for (int i = 0; i < wordCount; i++) {
            set.add(in.next());
        }
        // 保存商品名称
        String[] items = new String[itemCount];
        // 0存储商品下标,1存储商品关键词数量
        int[][] arr = new int[itemCount][2];
        // 统计商品对应的关键词数量
        for (int i = 0; i < itemCount; i++) {
            items[i] = in.next();
            arr[i][0] = i;
            int count = in.nextInt();
            for (int j = 0; j < count; j++) {
                String word = in.next();
                if (set.contains(word)) {
                    arr[i][1]++;
                }
            }
        }
        // 按照商品关键词数量排序
        Arrays.sort(arr, (a, b) -> b[1] - a[1]);
        for (int i = 0; i < itemCount; i++) {
            System.out.println(items[arr[i][0]]);
        }
    }
}


编辑于 2025-05-25 15:41:49 回复(0)
用哈希表存储需要配对的字符串,再用map去记录不同出现次数的字符串有哪些,最后sort快排输出。耗时59ms
#include <iostream>

#include <sstream>
#include<unordered_set>
#include<queue>
#include<unordered_map>
#include<algorithm>
using namespace std;
int main() {
    int n,q;
    cin>>n>>q;
    cin.ignore();
    unordered_set<string>st;
    string s;
    stringstream ss;
    getline(cin,s);
    ss.str(s);
    while(getline(ss,s,' ')){
        st.insert(s);
    }
    unordered_map<int,vector<string>>mp;
    for(int i=0;i<n;++i){
        string name;int a;
        cin>>name>>a;
        cin.ignore();
        string tmp;
        stringstream s1;
        getline(cin,tmp);
        s1.str(tmp);
        int times=0;
        while(getline(s1,tmp,' ')){
            if(st.find(tmp)!=st.end()){
                times++;
            }
        }
        mp[times].push_back(name);
    }
    vector<pair<int,vector<string>>>v;
    for(auto c:mp){
        v.push_back({c.first,c.second});
    }
    sort(v.begin(),v.end());
    for(int i=v.size()-1;i>=0;--i){
        for(int j=0;j<v[i].second.size();++j)
        cout<<v[i].second[j]<<endl;
    }
}


发表于 2025-06-05 16:21:54 回复(0)
#include <iostream>
using namespace std;
#include <unordered_set>
#include <string>
#include <unordered_map>
#include <vector>
#include <algorithm> 

static bool cmp(const pair<int, int> &a, const pair<int, int> &b){
    if(a.second == b.second){
        return a.first < b.first;
    }
    return a.second > b.second;
}

int main() {
    int n, q;
    cin >> n >> q;
    std::unordered_set<string> keywords;
    for(int i = 0; i < q; i++){
        string keyword;
        cin >> keyword;
        keywords.insert(keyword);
    }
    vector<string> products;
    std::unordered_map<int, int> record; // 记录商品的输入顺序,和包含关键词数量
    // 读取每个商品的信息  
    for (int i = 0; i < n; ++i) {  
        string name;  
        int m_i; 
        int count = 0; 
        cin >> name >> m_i;  
        products.push_back(name);
        for (int j = 0; j < m_i; ++j) {
            string k_p;  
            cin >> k_p;  
            if(keywords.find(k_p) != keywords.end()){
                count++;
            }
        }
        record.insert(pair<int, int>(i, count));
    } 
    vector<pair<int, int>> vec(record.begin(), record.end());
    std::sort(vec.begin(), vec.end(), cmp);
    for(int i = 0; i < n; i++){
        cout << products[vec[i].first] << endl;
    }
    return 0;
}
// 64 位输出请用 printf("%lld")

发表于 2025-04-10 15:36:33 回复(0)
import java.util.Scanner;
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int productNum = in.nextInt();
        int wordsNum = in.nextInt();
        in.nextLine();
        Set<String> wordsDict = new HashSet<>();
        for (int i = 0; i < wordsNum; i++) {
            String temp = in.next();
            wordsDict.add(temp);
        }
        in.nextLine();
        List<Product> productList = new ArrayList<>();
        for (int i = 0; i < productNum; i++) {
            String name = in.next();
            int num = in.nextInt();
            in.nextLine();
            List<String> words = new ArrayList<>();
            Collections.addAll(words, in.nextLine().split(" "));
            productList.add(new Product(name, words, i));
        }
        for (Product product: productList){
            for (String word: product.words){
                if (wordsDict.contains(word)) {
                    product.sameWordsNum++;
                }
            }
        }
//排序实现,先比较product包含的关键词数量,再比较输入顺序
        Collections.sort(productList, (p1, p2) -> {
            if (p1.sameWordsNum != p2.sameWordsNum) {
                return p2.sameWordsNum - p1.sameWordsNum;
            }
            else{
                return p1.priority - p2.priority;
            }
        });
        for (Product product: productList){
            System.out.println(product.name);
        }
    }
}
class Product {
    String name;
    List<String> words;
    int sameWordsNum = 0;
    int priority;
    Product(String name, List<String> words, int priority) {
        this.name = name;
        this.words = words;
        this.priority = priority;
    }
}
发表于 2025-03-27 20:59:09 回复(1)
刚开始用PriorityQueue写超时,原因是每次加入新节点都会排序,太耗时了。后面换List统一add最后排序,一次O(NlogN)即可,运行时间500ms。
import java.io.*;
import java.util.*;

public class Main {
    static class Product {
        String name;
        int count;
        int order;
        
        public Product(String name, int count, int order) {
            this.name = name;
            this.count = count;
            this.order = order;
        }
    }

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String[] nq = br.readLine().split(" ");
        int n = Integer.parseInt(nq[0]);
        int q = Integer.parseInt(nq[1]);
        
        Set<String> keywordSet = new HashSet<>(Arrays.asList(br.readLine().split(" ")));
        
        List<Product> products = new ArrayList<>(n);
        for (int i = 0; i < n; i++) {
            String[] parts = br.readLine().split(" ");
            String name = parts[0];
            int m = Integer.parseInt(parts[1]);
            
            String[] keywords = br.readLine().split(" ");
            int count = 0;
            for (String kw : keywords) {
                if (keywordSet.contains(kw)) count++;
            }
            
            products.add(new Product(name, count, i));
        }
        
        products.sort((a, b) -> {
            if (a.count != b.count) {
                return Integer.compare(b.count, a.count);
            } else {
                return Integer.compare(a.order, b.order);
            }
        });
        
        StringBuilder sb = new StringBuilder();
        for (Product p : products) {
            sb.append(p.name).append('\n');
        }
        System.out.print(sb);
    }
}


发表于 2025-03-19 22:54:23 回复(1)