算法题分享 | 最大单词长度乘积

31 阅读2分钟

【可商素材17】夜晚小巷_3_沐泠杳_来自小红书网页版.jpg

题目

给你一个字符串数组 words ,找出并返回 length(words[i]) * length(words[j]) 的最大值,并且这两个单词不含有公共字母。如果不存在这样的两个单词,返回 0 。

示例 1:

输入: words = ["abcw","baz","foo","bar","xtfn","abcdef"]
输出: 16 
解释 : 这两个单词为 "abcw", "xtfn"

示例 2:

输入: words = ["a","ab","abc","d","cd","bcd","abcd"]
输出: 4 
解释 : 这两个单词为 "ab", "cd"

示例 3:

输入: words = ["a","aa","aaa","aaaa"]
输出: 0 
解释 : 不存在这样的两个单词。

 

提示:

  • 2 <= words.length <= 1000
  • 1 <= words[i].length <= 1000
  • words[i] 仅包含小写字母

题解

解题思路

可以遍历字符串数组的每一对单词,判断是否不含有公共字母,若是,就更新最大单词长度乘积。遍历的时间复杂度为 O(n²),总的时间复杂度还得取决于是否含有公共字母的判断,如果简单粗暴的逐个字母进行判断,那么最终的总时间复杂度是会大于 O(n²) 的,这里可以基于 位运算 进行优化。

我们可以使用整数的二进制低位 0 ~ 25 位分别表示字母的 a ~ z,位取值为 1 表示字符串中含有对应的字母,只需要在初始化时得到字符串数组中每个字符串对应的掩码整数,即得到 mask 数组,那么后续在判断两字符串是否不存在公共字母时只需要判断 mask[i] & mask[j] == 0 是否成立即可,这样一来时间复杂度就降到了 O(n²),只不过多了初始化 mask 数组的时间复杂度 O(L),其中 L 为所有字符串的长度总和。

代码

class Solution {
    public int maxProduct(String[] words) {
        int n = words.length;
        int[] mask = new int[n];

        // 初始化掩码数组
        for (int i = 0; i < n; i++) {
            String str = words[i];
            for (int j = 0; j < str.length(); j++) {
                mask[i] |= 1 << (str.charAt(j) - 'a');
            }
        }

        int ans = 0;
        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                if ((mask[i] & mask[j]) == 0) {
                    int val = words[i].length() * words[j].length();
                    ans = val > ans ? val : ans;
                }
            }
        }

        return ans;
    }
}

复杂度分析

  • 时间复杂度:O(L+n²)

  • 空间复杂度:O(n)

优质项目推荐

推荐一个可用于练手、毕业设计参考、增加简历亮点的项目。

lemon-puls/txing-oj-backend: Txing 在线编程学习平台,集在线做题、编程竞赛、即时通讯、文章创作、视频教程、技术论坛为一体

公众号

有兴趣可以关注公众号一起学习更多的干货哈!

扫码_搜索联合传播样式-白色版.png