字节跳动笔试真题

# 字节跳动笔试真题

# 🏢 公司简介

字节跳动是全球领先的移动互联网公司,笔试题目注重算法创新、系统性能和用户体验。

# 📝 题目特点

  • 算法创新:考查对新颖算法问题的思考能力
  • 性能优化:关注算法的效率和优化
  • 实际应用:结合抖音、今日头条等产品场景
  • 思维敏捷:题目变化多样,考查应变能力

# 🎯 2024年春招真题

# 题目1:抖音视频推荐算法 🟡

题目描述: 设计一个视频推荐算法,根据用户的观看历史、点赞记录和视频特征,推荐用户可能感兴趣的视频。

输入:

  • 用户观看历史
  • 用户点赞记录
  • 视频特征矩阵
  • 推荐数量k

输出:

  • 推荐的k个视频ID

解题思路:

class Video {
    int id;
    String category;
    Set<String> tags;
    double popularity;
    int duration;
    
    public Video(int id, String category, Set<String> tags, double popularity, int duration) {
        this.id = id;
        this.category = category;
        this.tags = tags;
        this.popularity = popularity;
        this.duration = duration;
    }
}

class UserProfile {
    Set<Integer> watchedVideos;
    Set<Integer> likedVideos;
    Map<String, Double> categoryPreference;
    Map<String, Double> tagPreference;
    
    public UserProfile() {
        this.watchedVideos = new HashSet<>();
        this.likedVideos = new HashSet<>();
        this.categoryPreference = new HashMap<>();
        this.tagPreference = new HashMap<>();
    }
}

public List<Integer> recommendVideos(UserProfile user, List<Video> allVideos, int k) {
    List<VideoScore> candidates = new ArrayList<>();
    
    for (Video video : allVideos) {
        if (!user.watchedVideos.contains(video.id)) {
            double score = calculateScore(user, video);
            candidates.add(new VideoScore(video.id, score));
        }
    }
    
    return candidates.stream()
            .sorted((a, b) -> Double.compare(b.score, a.score))
            .limit(k)
            .map(vs -> vs.videoId)
            .collect(Collectors.toList());
}

private double calculateScore(UserProfile user, Video video) {
    double score = 0.0;
    
    // 类别偏好
    score += user.categoryPreference.getOrDefault(video.category, 0.0) * 0.4;
    
    // 标签偏好
    for (String tag : video.tags) {
        score += user.tagPreference.getOrDefault(tag, 0.0) * 0.3;
    }
    
    // 视频热度
    score += video.popularity * 0.2;
    
    // 时长偏好(假设用户喜欢中等时长的视频)
    score += Math.exp(-Math.abs(video.duration - 60) / 30.0) * 0.1;
    
    return score;
}

class VideoScore {
    int videoId;
    double score;
    
    public VideoScore(int videoId, double score) {
        this.videoId = videoId;
        this.score = score;
    }
}

# 题目2:今日头条热搜排行榜 🟠

题目描述: 实现一个实时热搜排行榜,根据关键词的搜索频次和时间衰减因子计算热度。

输入:

  • 搜索记录流(关键词、时间戳)
  • 时间窗口大小
  • 衰减因子

输出:

  • 实时热搜排行榜(前k个关键词)

解题思路:

class HotSearchRanking {
    private Map<String, Double> keywordScores;
    private Map<String, List<Long>> keywordTimestamps;
    private double decayFactor;
    private long timeWindow;
    
    public HotSearchRanking(double decayFactor, long timeWindow) {
        this.keywordScores = new HashMap<>();
        this.keywordTimestamps = new HashMap<>();
        this.decayFactor = decayFactor;
        this.timeWindow = timeWindow;
    }
    
    public void addSearch(String keyword, long timestamp) {
        // 清理过期数据
        cleanExpiredData(timestamp);
        
        // 添加新搜索记录
        keywordTimestamps.computeIfAbsent(keyword, k -> new ArrayList<>()).add(timestamp);
        
        // 更新热度分数
        updateScore(keyword, timestamp);
    }
    
    public List<String> getTopK(int k, long currentTime) {
        cleanExpiredData(currentTime);
        
        return keywordScores.entrySet().stream()
                .sorted((a, b) -> Double.compare(b.getValue(), a.getValue()))
                .limit(k)
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());
    }
    
    private void updateScore(String keyword, long timestamp) {
        List<Long> timestamps = keywordTimestamps.get(keyword);
        double score = 0.0;
        
        for (long ts : timestamps) {
            double timeDiff = (timestamp - ts) / 1000.0; // 转换为秒
            score += Math.exp(-decayFactor * timeDiff);
        }
        
        keywordScores.put(keyword, score);
    }
    
    private void cleanExpiredData(long currentTime) {
        long expireTime = currentTime - timeWindow;
        
        keywordTimestamps.entrySet().removeIf(entry -> {
            List<Long> timestamps = entry.getValue();
            timestamps.removeIf(ts -> ts < expireTime);
            return timestamps.isEmpty();
        });
        
        keywordScores.entrySet().removeIf(entry -> 
            !keywordTimestamps.containsKey(entry.getKey()));
    }
}

# 题目3:飞书文档协同编辑 🔴

题目描述: 设计一个文档协同编辑系统,支持多用户同时编辑,需要处理操作冲突和保证数据一致性。

输入:

  • 用户操作序列(插入、删除、修改)
  • 操作时间戳
  • 用户ID

输出:

  • 最终的文档内容
  • 操作冲突解决方案

解题思路:

class Operation {
    enum Type { INSERT, DELETE, MODIFY }
    
    Type type;
    int position;
    String content;
    long timestamp;
    String userId;
    
    public Operation(Type type, int position, String content, long timestamp, String userId) {
        this.type = type;
        this.position = position;
        this.content = content;
        this.timestamp = timestamp;
        this.userId = userId;
    }
}

class CollaborativeEditor {
    private StringBuilder document;
    private List<Operation> operationHistory;
    private Map<String, Long> userVersions;
    
    public CollaborativeEditor() {
        this.document = new StringBuilder();
        this.operationHistory = new ArrayList<>();
        this.userVersions = new HashMap<>();
    }
    
    public synchronized String applyOperation(Operation op) {
        // 检查操作是否有效
        if (!isValidOperation(op)) {
            return "Invalid operation";
        }
        
        // 转换操作位置(处理并发冲突)
        Operation transformedOp = transformOperation(op);
        
        // 应用操作
        switch (transformedOp.type) {
            case INSERT:
                document.insert(transformedOp.position, transformedOp.content);
                break;
            case DELETE:
                int endPos = Math.min(transformedOp.position + transformedOp.content.length(), 
                                    document.length());
                document.delete(transformedOp.position, endPos);
                break;
            case MODIFY:
                int modifyEnd = Math.min(transformedOp.position + transformedOp.content.length(), 
                                       document.length());
                document.replace(transformedOp.position, modifyEnd, transformedOp.content);
                break;
        }
        
        // 记录操作历史
        operationHistory.add(transformedOp);
        userVersions.put(op.userId, op.timestamp);
        
        return document.toString();
    }
    
    private boolean isValidOperation(Operation op) {
        return op.position >= 0 && op.position <= document.length();
    }
    
    private Operation transformOperation(Operation op) {
        int adjustedPosition = op.position;
        
        // 根据历史操作调整位置
        for (Operation historyOp : operationHistory) {
            if (historyOp.timestamp < op.timestamp && 
                historyOp.position <= op.position) {
                
                switch (historyOp.type) {
                    case INSERT:
                        adjustedPosition += historyOp.content.length();
                        break;
                    case DELETE:
                        adjustedPosition -= historyOp.content.length();
                        break;
                }
            }
        }
        
        return new Operation(op.type, Math.max(0, adjustedPosition), 
                           op.content, op.timestamp, op.userId);
    }
    
    public String getDocument() {
        return document.toString();
    }
}

# 🔍 历年高频考点

# 算法类

  • 滑动窗口(最大/最小值问题)
  • 双指针技巧(快慢指针、左右指针)
  • 分治算法(归并排序、快速选择)
  • 贪心算法(区间调度、活动选择)

# 数据结构类

  • 堆和优先队列
  • 字典树(Trie)
  • 并查集(Union-Find)
  • 线段树和树状数组

# 系统设计类

  • 分布式缓存
  • 消息队列
  • 负载均衡
  • 数据一致性

# 💡 备考建议

  1. 算法思维:培养快速分析问题的能力
  2. 代码实现:注重代码的简洁性和效率
  3. 系统理解:了解大规模系统的设计原理
  4. 创新思考:敢于尝试新的解题思路
  5. 时间控制:提高编码速度和准确性