318. 最大单词长度乘积 : 经典「状态压缩 + 位运算」入门题

简介: 318. 最大单词长度乘积 : 经典「状态压缩 + 位运算」入门题

网络异常,图片无法展示
|


题目描述



这是 LeetCode 上的 318. 最大单词长度乘积 ,难度为 中等


Tag : 「模拟」、「位运算」、「哈希表」


给定一个字符串数组 words,找到 length(word[i]) *

length(word[j])length(word[i])length(word[j]) 的最大值,并且这两个单词不含有公共字母。你可以认为每个单词只包含小写字母。如果不存在这样的两个单词,返回 00


示例 1:


输入: ["abcw","baz","foo","bar","xtfn","abcdef"]
输出: 16 
解释: 这两个单词为 "abcw", "xtfn"。
复制代码


示例 2:


输入: ["a","ab","abc","d","cd","bcd","abcd"]
输出: 4 
解释: 这两个单词为 "ab", "cd"。
复制代码


示例 3:


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


提示:


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


模拟



根据题意进行模拟即可,利用每个 words[i]words[i] 只有小写字母,且只需要区分两字符是否有字母重复。


我们可以使用一个 int 来代指某个 word[i]word[i]:低 2626 来代指字母 a-z 是否出现过。


然后对每个「字符对」所对应的两个 int 值执行 & 操作(若两字符无重复字符,则结果为 00),并得出最终答案。


代码:


class Solution {
    public int maxProduct(String[] words) {
        int n = words.length, idx = 0;
        int[] masks = new int[n];
        for (String w : words) {
            int t = 0;
            for (int i = 0; i < w.length(); i++) {
                int u = w.charAt(i) - 'a';
                t |= (1 << u);
            }
            masks[idx++] = t;
        }
        int ans = 0;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < i; j++) {
                if ((masks[i] & masks[j]) == 0) ans = Math.max(ans, words[i].length() * words[j].length());
            }
        }
        return ans;
    }
}
复制代码


  • 时间复杂度:令 nnwordswords 数组的长度,转换出 masksmasks 的复杂度为 O(\sum_{i = 0}^{i = n - 1}words[i].length)O(i=0i=n1words[i].length);得到答案的复杂度为 O(n^2)O(n2)。整体复杂度为 O(\max(\sum_{i = 0}^{i = n - 1}words[i].length, n^2))O(max(i=0i=n1words[i].length,n2))
  • 空间复杂度:O(n)O(n)


优化



不难发现,对于词频相同(maskmask 值相等)的两字符,只需要保留字符长度大的即可,因此我们可以使用「哈希表」代替 masksmasks 数组。


代码:


class Solution {
    public int maxProduct(String[] words) {
        Map<Integer, Integer> map = new HashMap<>();
        for (String w : words) {
            int t = 0, m = w.length();
            for (int i = 0; i < m; i++) {
                int u = w.charAt(i) - 'a';
                t |= (1 << u);
            }
            if (!map.containsKey(t) || map.get(t) < m) map.put(t, m);
        }
        int ans = 0;
        for (int a : map.keySet()) {
            for (int b : map.keySet()) {
                if ((a & b) == 0) ans = Math.max(ans, map.get(a) * map.get(b));
            }
        }
        return ans;
    }
}
复制代码


  • 时间复杂度:令 nnwordswords 数组的长度,得到 mapmap 的复杂度为 O(\sum_{i = 0}^{i = n - 1}words[i].length)O(i=0i=n1words[i].length);得到答案的复杂度为 O(n^2)O(n2)。整体复杂度为 O(\max(\sum_{i = 0}^{i = n - 1}words[i].length, n^2))O(max(i=0i=n1words[i].length,n2))
  • 空间复杂度:O(n)O(n)


最后



这是我们「刷穿 LeetCode」系列文章的第 No.318 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。


在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。


为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:github.com/SharingSour…


在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。

相关文章
|
新零售 机器学习/深度学习 人工智能
云栖新闻|助力企业智能化升级 达摩院“新一代企业智能服务论坛”圆满举行
介绍阿里云智能客服最新进展,包括全渠道全场景覆盖的云上产品矩阵,从智能服务向智能营销场景延申的解决方案,国内首创的智能策略中心的发布,号召客户和生态伙伴与我们圆桌探讨智能服务行业未来。
云栖新闻|助力企业智能化升级 达摩院“新一代企业智能服务论坛”圆满举行
|
机器学习/深度学习 算法 Python
【Python强化学习】时序差分法Sarsa算法和Qlearning算法在冰湖问题中实战(附源码)
【Python强化学习】时序差分法Sarsa算法和Qlearning算法在冰湖问题中实战(附源码)
226 1
|
人工智能 算法 自动驾驶
人工智能的伦理挑战与社会责任
【8月更文挑战第10天】随着人工智能技术的飞速发展,其在社会各领域的应用日益广泛。然而,AI技术在带来便利的同时,也引发了一系列伦理问题和社会责任问题。本文将探讨AI技术可能带来的伦理挑战,以及作为技术开发者、应用者和监管者的我们应如何承担起相应的社会责任,确保AI技术的健康发展,服务于人类的福祉。
|
9月前
|
关系型数据库 MySQL 数据库
CDC YAML 在阿里云的最佳实践
本文撰写自阿里云开源大数据平台数据通道团队,主要介绍了 Flink CDC YAML 在实时计算Flink版的最佳实践。
662 4
CDC YAML 在阿里云的最佳实践
|
11月前
|
Python
【10月更文挑战第6天】「Mac上学Python 10」基础篇4 - 布尔类型详解
本篇将详细介绍Python中的布尔类型及其应用,包括布尔值、逻辑运算、关系运算符以及零值的概念。布尔类型是Python中的一种基本数据类型,广泛应用于条件判断和逻辑运算中,通过本篇的学习,用户将掌握如何使用布尔类型进行逻辑操作和条件判断。
164 1
【10月更文挑战第6天】「Mac上学Python 10」基础篇4 - 布尔类型详解
|
9月前
|
Web App开发 网络协议 安全
网络编程懒人入门(十六):手把手教你使用网络编程抓包神器Wireshark
Wireshark是一款开源和跨平台的抓包工具。它通过调用操作系统底层的API,直接捕获网卡上的数据包,因此捕获的数据包详细、功能强大。但Wireshark本身稍显复杂,本文将以用抓包实例,手把手带你一步步用好Wireshark,并真正理解抓到的数据包的各项含义。
1269 2
|
Rust 测试技术 编译器
Rust与C++的区别及使用问题之Rust项目中组织目录结构的问题如何解决
Rust与C++的区别及使用问题之Rust项目中组织目录结构的问题如何解决
172 1
|
安全 Android开发 数据安全/隐私保护
Android中的动态权限请求与最佳实践
【4月更文挑战第14天】 在现代安卓应用开发中,用户隐私和安全被赋予了前所未有的重要性。随着Android 6.0(API级别23)引入的运行时权限模型,开发者必须更加细致地处理权限请求,以确保应用功能的完整性同时不侵犯用户的隐私。本文将深入探讨如何在Android应用中实现动态权限请求,分析常见问题,并提供一系列最佳实践,以帮助开发者优雅地处理这一挑战。
626 5
|
机器学习/深度学习 并行计算 编译器
MXNet安装教程:详细步骤与常见问题解析
【4月更文挑战第12天】本文详细介绍了MXNet深度学习框架的安装步骤,包括Python、conda和R用户的安装方法,以及GPU支持的选项。在安装过程中可能遇到网络问题、依赖冲突和GPU支持问题等,文中给出了相应解决策略。安装后,通过简单的代码示例验证MXNet是否正常工作,从而顺利完成本地环境搭建。
2224 7
|
XML 存储 数据库
工作流JBPM系统数据库表介绍
工作流JBPM系统数据库表介绍
112 1