51mee - AI智能招聘平台Logo
模拟面试题目大全招聘中心会员专区

设计一个简单的用户行为推荐系统,根据用户历史课程选择推荐新课程,请用Golang实现一个基于协同过滤的简化版本(如计算用户相似度,推荐相似用户喜欢的课程),并说明时间复杂度。

好未来Golang难度:中等

答案

1) 【一句话结论】
基于协同过滤的简化用户行为推荐系统,通过计算用户历史课程选择的相似度(如余弦相似度),推荐相似用户喜欢的未浏览课程,核心实现包括用户-课程行为矩阵构建、相似度计算、推荐生成,时间复杂度主要取决于相似度计算步骤(如O(n²·m))。

2) 【原理/概念讲解】
老师口吻:协同过滤(Collaborative Filtering)是利用用户行为数据(如课程选择)进行推荐的核心方法,核心思想是“物以类聚,人以群分”——用户行为相似则偏好相似。本题简化为用户-用户协同过滤:

  • 用户-课程行为矩阵:记录每个用户选过的课程(如用户ID → 课程列表);
  • 相似度计算:将每个用户的行为看作一个“兴趣向量”(课程为维度,选为1,未选为0),用余弦相似度衡量向量夹角(夹角越小越相似,公式为交集大小 / (|用户A行为向量| × |用户B行为向量|));
  • 推荐逻辑:对目标用户,找出相似度最高的k个用户,汇总这些用户喜欢的课程(排除目标用户已选的),作为推荐结果。
    类比:把用户行为看作“兴趣向量”,相似度计算就是看两个向量是否“方向接近”,方向越接近,用户越相似(比如用户A选了数学、英语,向量是[1,1];用户B选了数学、物理,向量是[1,1],两者方向接近,相似度高)。

3) 【对比与适用场景】

对比维度协同过滤(用户-用户)基于内容的推荐(物品-物品)
定义根据用户行为数据推荐,核心是用户相似度根据物品特征(如课程标签、难度)推荐,核心是物品相似度
特性依赖用户行为数据,能发现未知偏好,但冷启动问题(新用户/新课程)较严重依赖物品特征,能解释推荐原因,但推荐可能同质化
使用场景用户行为数据丰富(如课程选择记录多)的场景,如教育平台推荐课程物品特征明确(如课程有标签、评分)的场景,或用户行为稀疏时
注意点需处理数据稀疏性(用户选课少)、冷启动问题、计算复杂度高(计算所有用户对相似度)需准确提取物品特征,特征维度高时计算复杂,推荐可能局限于已知特征

4) 【示例】
伪代码(Golang风格):

// 用户-课程行为矩阵,用户ID -> 课程列表
type UserCourseMap map[int][]string

// 计算用户u和v的余弦相似度
func cosineSimilarity(u, v UserCourseMap) float64 {
    vecU := make(map[string]bool)
    for _, c := range u {
        vecU[c] = true
    }
    vecV := make(map[string]bool)
    for _, c := range v {
        vecV[c] = true
    }
    
    common := 0
    lenU := len(vecU)
    lenV := len(vecV)
    
    for c := range vecU {
        if vecV[c] {
            common++
        }
    }
    
    if lenU == 0 || lenV == 0 {
        return 0
    }
    return float64(common) / (float64(lenU) * float64(lenV))
}

// 推荐函数:为用户u推荐k个课程
func recommendCourses(userMap UserCourseMap, user int, k int) []string {
    selectedCourses := userMap[user]
    similarities := make(map[int]float64)
    for otherUser, _ := range userMap {
        if otherUser == user {
            continue
        }
        sim := cosineSimilarity(userMap[otherUser], userMap[user])
        similarities[otherUser] = sim
    }
    
    sortedUsers := sortUsersBySimilarity(similarities)
    
    recommended := make(map[string]bool)
    for _, otherUser := range sortedUsers {
        for _, course := range userMap[otherUser] {
            if !contains(selectedCourses, course) {
                recommended[course] = true
            }
        }
    }
    
    result := make([]string, 0, len(recommended))
    for course := range recommended {
        result = append(result, course)
    }
    return result
}

func contains(list []string, course string) bool {
    for _, c := range list {
        if c == course {
            return true
        }
    }
    return false
}

func sortUsersBySimilarity(simMap map[int]float64) []int {
    users := make([]int, 0, len(simMap))
    for user, _ := range simMap {
        users = append(users, user)
    }
    sort.Slice(users, func(i, j int) bool {
        return simMap[users[i]] > simMap[users[j]]
    })
    return users
}

时间复杂度分析:计算所有用户对相似度时,假设有n个用户,每个用户平均有m个课程,总复杂度为O(n²·m)(每个用户需遍历其他n-1个用户,比较时遍历各自的m个课程)。实际可通过“只计算前k个相似用户”优化(k远小于n)。

5) 【面试口播版答案】
“面试官您好,我设计的这个用户行为推荐系统是基于协同过滤的简化版本,核心思路是计算用户历史课程选择的相似度,然后推荐相似用户喜欢的课程。首先,我们构建一个用户-课程行为矩阵,记录每个用户选过的课程。然后,计算任意两个用户之间的相似度,这里我用余弦相似度,把每个用户的行为看作一个向量,向量元素是课程是否被选择,相似度就是两个向量夹角的大小,夹角越小越相似。接着,对于目标用户,找出相似度最高的k个用户,汇总这些用户喜欢的课程(排除目标用户已选的),作为推荐结果。时间复杂度方面,主要步骤是计算所有用户对的相似度,假设有n个用户,每个用户平均有m个课程,那么复杂度是O(n²·m),不过实际中可以通过只计算前k个相似用户来优化。”

6) 【追问清单】

  • 问:时间复杂度具体怎么计算的?有没有更优化的方法?
    回答要点:计算所有用户对相似度时,复杂度是O(n²·m),因为每个用户需要和其他n-1个用户比较,比较时遍历各自的m个课程。优化方法可以是只计算前k个相似用户(k远小于n),或使用近似算法(如基于树的相似度计算)。
  • 问:如何处理新用户(冷启动)问题?
    回答要点:新用户没有历史行为数据,无法计算相似度,此时可采用基于内容的推荐(如根据课程标签、难度等特征推荐),或给新用户推荐热门课程、系统默认推荐。
  • 问:如果课程数量很多,如何优化相似度计算?
    回答要点:当课程数量m很大时,用户-用户相似度计算会变慢,可采用物品-物品协同过滤(计算课程之间的相似度,推荐与用户已选课程相似的课程),或使用矩阵分解(如SVD)降低维度。
  • 问:如何处理数据稀疏性问题(比如很多用户只选过1-2门课)?
    回答要点:数据稀疏时,余弦相似度可能不准确,可改用Jaccard相似度(考虑集合的交集和并集),或增加用户行为数据(如延长观察周期)。
  • 问:推荐结果如何排序?有没有考虑用户偏好权重?
    回答要点:推荐结果可按相似用户数量或相似度高低排序,或结合用户历史行为的权重(如最近选的课程权重更高)。另外,冷启动时可给新用户推荐系统默认的热门课程。

7) 【常见坑/雷区】

  • 时间复杂度计算错误:误认为计算所有用户对相似度是O(n³),或没考虑m的影响;
  • 推荐逻辑错误:推荐了相似用户已选的课程,或没排除用户已选的课程;
  • 冷启动问题没提及:面试官会追问新用户/新课程如何处理,若没准备会被扣分;
  • 相似度计算方法错误:用欧氏距离计算用户行为相似度(用户行为是二元变量,应使用余弦/ Jaccard);
  • 忽略数据稀疏性:当用户行为数据稀疏时,相似度计算结果不可靠,需说明如何处理。
51mee.com致力于为招聘者提供最新、最全的招聘信息。AI智能解析岗位要求,聚合全网优质机会。
产品招聘中心面经会员专区简历解析Resume API
联系我们南京浅度求索科技有限公司admin@51mee.com
联系客服
51mee客服微信二维码 - 扫码添加客服获取帮助
© 2025 南京浅度求索科技有限公司. All rights reserved.
公安备案图标苏公网安备32010602012192号苏ICP备2025178433号-1