如何判断一个字符串是否包含另一个字符串的所有字符(考虑字符数量)

该方法用于检查字符串 word1 是否包含字符串 word2 中的**全部字符(含重复次数)**,顺序无关,但需确保每个字符的出现频次不超出 word1 中的实际数量。

在 Java 中,简单使用 String.contains() 或逐字符检查(如原代码中 word1.contains(itemPiece))无法处理字符重复计数问题——例如 word1 = "12345++" 和 word2 = "155",虽然 word1 中只有一个 '5',但原逻辑会两次匹配 '5',错误返回 true。

根本原因在于:contains() 是无状态、全局匹配,不消耗字符;而我们需要的是带频次约束的多对一匹配——即 word2 中每个字符必须在 word1 中有唯一对应(用过即失效)。

✅ 推荐解法是使用 ArrayList 动态维护 word1 的可用字符池:

import java.util.*;

public static boolean isItemUsable2(String word1, String word2) {
    // 边界处理:空字符串视为有效(若业务要求 word2 为空时返回 true)
    if (word2 == null || word2.isEmpty()) return true;
    if (word1 == null) return false;

    // 构建 word1 字符池(保留所有字符,含重复)
    List availableChars = new ArrayList<>();
    for (char c : word1.toCharArray()) {
        availableChars.add(c);
    }

    // 尝试为 word2 中每个字符寻找唯一匹配
    for (char target : word2.toCharArray()) {
        // remove(Object) 返回 boolean:成功移除返回 

true,未找到返回 false if (!availableChars.remove((Character) target)) { return false; // 某个字符缺失或已用尽 } } return true; }

? 关键细节说明:

  • availableChars.remove((Character) target) 使用的是 对象移除(remove(Object)),而非按索引移除(remove(int)),因此会删除列表中第一个匹配的字符实例
  • 强制类型转换 (Character) target 是必需的,否则会误调用 remove(int index) 导致 IndexOutOfBoundsException;
  • 时间复杂度为 O(m × n),其中 m = word1.length(),n = word2.length()(ArrayList.remove() 平均 O(n));如需更高性能(如超长字符串),可改用 HashMap 统计频次(O(m + n))。

? 进阶优化(频次哈希表版,推荐用于大数据量):

public static boolean isItemUsable2Optimized(String word1, String word2) {
    if (word2 == null || word2.isEmpty()) return true;
    if (word1 == null) return false;

    // 统计 word1 中各字符出现次数
    Map charCount = new HashMap<>();
    for (char c : word1.toCharArray()) {
        charCount.put(c, charCount.getOrDefault(c, 0) + 1);
    }

    // 消耗 word2 中每个字符
    for (char c : word2.toCharArray()) {
        int count = charCount.getOrDefault(c, 0);
        if (count <= 0) return false;
        charCount.put(c, count - 1);
    }
    return true;
}

✅ 总结:解决“含重复字符的子集判定”问题,核心在于状态化匹配——要么动态消耗字符池(ArrayList),要么预统计频次(HashMap)。避免使用无状态的 contains(),它只回答“是否存在”,而非“是否足够”。