🌕🌗 318. 最大单词长度乘积

吞佛童子2022年10月10日
  • algorithm
  • 位运算
大约 2 分钟

🌕🌗 318. 最大单词长度乘积

难度: 🌕🌗

问题描述

img_27.png


解法 1

class Solution {
    public int maxProduct(String[] words) {
        // 思路:
        // 位运算
        // 直接想法就是依次遍历每个单词,判断和其他单词是否有公共字母,若不存在,更新 res
        // 如何判断 cur & 其他单词 是否有公共字母?
        // 由于只含小写字母,最直接方法是 cur 映射到一个 boolean[26] 中,其他单词也映射到一个 boolean[26] 中,取交集
        // 但是这样复杂度比较高,我们只需要判断对应 下标 是否存在,也无需管对应下标处的字符次数
        // 因此可以将 boolean[26] 折算成一个 int 值,通过 1<< index 得到 int

        int len = words.length;
        int[] array = new int[len]; // 存放不同下标单词 映射的 int 值
        for(int i = 0; i < len; i ++) {
            String cur = words[i];
            int val = 0;
            // 遍历 当前单词 的每个字符,进行映射
            for(int j = 0; j < cur.length(); j ++) {
                int left = cur.charAt(j) - 'a'; // 需要左移的位数
                val |= (1 << left);
            }
            array[i] = val;
        }

        int res = 0;
        for(int i = 0; i < len - 1; i ++) {
            for(int j = i + 1; j < len; j ++) {
                if((array[i] & array[j]) == 0) {
                    // 说明 [0, 25] 位中没有同时出现的 1,即没有公共字母,更新 res
                    res = Math.max(res, words[i].length() * words[j].length());
                }
            }
        }
        return res;
    }
}

输出 1

img_26.png


解法 - 优化

class Solution {
    public int maxProduct(String[] words) {
        // 思路:
        // 由于 {meet, met, memet} 这类单词最终映射的 val 均相同,因此可以通过 HashMap 存储 val
        // 遍历的时候,也只遍历 map 集合,而非 word[] 
        // 当 这类单词 经常出现时,针对这种用例,可以达到优化效果
        int len = words.length;
        HashMap<Integer, Integer> map = new HashMap<>(); // val - val 对应的最长单词长度
        
        for(String cur: words) {
            int size = cur.length();
            int val = 0;
            for(int j = 0; j < size; j ++) {
                int left = cur.charAt(j) - 'a';
                val |= (1 << left);
            }
            if(!map.containsKey(val)) {
                map.put(val, size);
            } else {
                int preLen = map.get(val);
                if(size > preLen) {
                    map.put(val, size); // 更新 val 对应的最长单词长度
                }
            }
        }

        // 遍历 map
        int res = 0;
        for(int a: map.keySet()) {
            for(int b: map.keySet()) {
                // 当 a == b 时,a & b 必 != 0,因此无需特殊情况特判
                if((a & b) == 0) {
                    res = Math.max(res, map.get(a) * map.get(b));
                }
            }
        }
        return res;
    }
}

输出

img_28.png

上次编辑于: 2022/10/10 下午8:43:48
贡献者: liuxianzhishou