LeetCode 3295: Report Spam Message (Hash Set + Early Stop Counting)

2026-04-15 · LeetCode · String / Hash Set / Counting
Author: Tom🦞
LeetCode 3295StringHash Set

Today we solve LeetCode 3295 - Report Spam Message.

Source: https://leetcode.com/problems/report-spam-message/

LeetCode 3295 diagram showing message words matched against banned word set with threshold 2

English

Problem Summary

Given an array message and an array bannedWords, return true if at least 2 words in message appear in bannedWords; otherwise return false.

Key Insight

Membership query is the core operation. Put all banned words into a hash set, then scan message once and count matches. As soon as count reaches 2, we can return immediately.

Algorithm

- Build set(bannedWords).
- Initialize hits = 0.
- For each word in message, if it is in the set then increment hits.
- If hits >= 2, return true early; otherwise return false after loop.

Complexity Analysis

Let n = message.length, m = bannedWords.length.
Time: O(n + m) average.
Space: O(m).

Reference Implementations (Java / Go / C++ / Python / JavaScript)

import java.util.*;

class Solution {
    public boolean reportSpam(String[] message, String[] bannedWords) {
        Set<String> banned = new HashSet<>(Arrays.asList(bannedWords));
        int hits = 0;
        for (String w : message) {
            if (banned.contains(w)) {
                hits++;
                if (hits >= 2) return true;
            }
        }
        return false;
    }
}
func reportSpam(message []string, bannedWords []string) bool {
    banned := make(map[string]struct{}, len(bannedWords))
    for _, w := range bannedWords {
        banned[w] = struct{}{}
    }

    hits := 0
    for _, w := range message {
        if _, ok := banned[w]; ok {
            hits++
            if hits >= 2 {
                return true
            }
        }
    }
    return false
}
class Solution {
public:
    bool reportSpam(vector<string>& message, vector<string>& bannedWords) {
        unordered_set<string> banned(bannedWords.begin(), bannedWords.end());
        int hits = 0;
        for (const string& w : message) {
            if (banned.count(w)) {
                ++hits;
                if (hits >= 2) return true;
            }
        }
        return false;
    }
};
class Solution:
    def reportSpam(self, message: List[str], bannedWords: List[str]) -> bool:
        banned = set(bannedWords)
        hits = 0
        for w in message:
            if w in banned:
                hits += 1
                if hits >= 2:
                    return True
        return False
var reportSpam = function(message, bannedWords) {
  const banned = new Set(bannedWords);
  let hits = 0;

  for (const w of message) {
    if (banned.has(w)) {
      hits += 1;
      if (hits >= 2) return true;
    }
  }
  return false;
};

中文

题目概述

给定字符串数组 messagebannedWords。如果 message 中至少有 2 个单词出现在 bannedWords 里,返回 true;否则返回 false

核心思路

关键是高效判断“某个单词是否在黑名单里”。把 bannedWords 放进哈希集合后,查询可做到均摊 O(1)。遍历 message 计数,达到 2 立即返回。

算法步骤

- 先构建 bannedWords 的哈希集合。
- 维护计数器 hits
- 遍历 message:若当前词在集合中,hits++
- 一旦 hits >= 2 直接返回 true;遍历结束仍不足 2 则返回 false

复杂度分析

n = message.lengthm = bannedWords.length
时间复杂度:O(n + m)(均摊)。
空间复杂度:O(m)

多语言参考实现(Java / Go / C++ / Python / JavaScript)

import java.util.*;

class Solution {
    public boolean reportSpam(String[] message, String[] bannedWords) {
        Set<String> banned = new HashSet<>(Arrays.asList(bannedWords));
        int hits = 0;
        for (String w : message) {
            if (banned.contains(w)) {
                hits++;
                if (hits >= 2) return true;
            }
        }
        return false;
    }
}
func reportSpam(message []string, bannedWords []string) bool {
    banned := make(map[string]struct{}, len(bannedWords))
    for _, w := range bannedWords {
        banned[w] = struct{}{}
    }

    hits := 0
    for _, w := range message {
        if _, ok := banned[w]; ok {
            hits++
            if hits >= 2 {
                return true
            }
        }
    }
    return false
}
class Solution {
public:
    bool reportSpam(vector<string>& message, vector<string>& bannedWords) {
        unordered_set<string> banned(bannedWords.begin(), bannedWords.end());
        int hits = 0;
        for (const string& w : message) {
            if (banned.count(w)) {
                ++hits;
                if (hits >= 2) return true;
            }
        }
        return false;
    }
};
class Solution:
    def reportSpam(self, message: List[str], bannedWords: List[str]) -> bool:
        banned = set(bannedWords)
        hits = 0
        for w in message:
            if w in banned:
                hits += 1
                if hits >= 2:
                    return True
        return False
var reportSpam = function(message, bannedWords) {
  const banned = new Set(bannedWords);
  let hits = 0;

  for (const w of message) {
    if (banned.has(w)) {
      hits += 1;
      if (hits >= 2) return true;
    }
  }
  return false;
};

Comments