当前位置: 首页 > news >正文

《剑指 Offer》专项突破版 - 面试题 5 : 单词长度的最大乘积(C++ 实现)

目录

前言

方法一

方法二


 


前言

题目链接:318. 最大单词长度乘积 - 力扣(LeetCode)

题目

输入一个字符串数组 words,请计算不包含相同字符的两个字符串 words[i] 和 words[j] 的长度乘积的最大值。如果所有字符串都包含至少一个相同的字符,那么返回 0。假设字符串中只包含英文小写字母。例如,输入的字符串数组 words 为 ["abcw", "foo", "bar", "fxyz", "abcdef"],数组中的字符串 "foo" 与 "bar" 没有相同的字符,它们的长度的乘积为 9;"abcw" 和 "fxyz" 也没有相同的字符,它们长度的乘积为 16,这是该数组中不包含相同字符的一对字符串的长度乘积的最大值。

分析

解决这个问题的关键在于如何判断两个字符串 str1 和 str2 中有没有相同的字符。一个直观的想法是基于字符串 str1 中的每个字符 ch,扫描字符串 str2 判断字符串 ch 是否出现在 str2 中。如果两个字符串的长度分别为 p 和 q,那么这种蛮力法的时间复杂度是 O(pq)。


方法一

可以用哈希表来优化时间效率。对于每个字符串,可以用一个哈希表记录出现在该字符串中的所有字符。在判断两个字符串是否有相同的字符时,只需要从 'a' 到 'z' 判断某个字符是否在两个字符串对应的哈希表中都出现了。在哈希表中查找的时间复杂度是 O(1)。这个题目假设所有字符都是英文小写字母,只有 26 个可能的字符,因此最多只需要在每个字符串对应的哈希表中查询 26 次就能判断两个字符串是否包含相同的字符。26 是一个常数,因此可以认为应用哈希表判断两个字符是否具有相同的字符的时间复杂度是 O(1)。

由于这个题目只需要考虑 26 个英文小写字母,因此可以用一个长度为 26 的布尔型数组来模拟哈希表。数组下标为 0 的值表示字符 'a' 是否出现,下标为 1 的值表示字符 'b' 是否出现,其余依次类推

写法一

class Solution {
public:int maxProduct(vector<string>& words) {int length = words.size();bool** flags = new bool*[length];for (int i = 0; i < length; ++i){flags[i] = new bool[26];for (int j = 0; j < 26; ++j){flags[i][j] = false;}}
​for (int i = 0; i < length; ++i){for (char ch : words[i]){flags[i][ch - 'a'] = true;}}
​int result = 0;for (int i = 0; i < length; ++i){for (int j = i + 1; j < length; ++j){int k = 0;for (; k < 26; ++k){if (flags[i][k] && flags[j][k])break;}
​if (k == 26){int product = words[i].size() * words[j].size();if (product > result)result = product;}}}
​for (int i = 0; i < length; ++i){delete[] flags[i];}delete[] flags;
​return result;}
};

写法二

class Solution {
public:int maxProduct(vector<string>& words) {int length = words.size();vector<vector<bool>> flags(length, vector<bool>(26, false));for (int i = 0; i < length; ++i){for (char ch : words[i]){flags[i][ch - 'a'] = true;}}
​int result = 0;for (int i = 0; i < length; ++i){for (int j = i + 1; j < length; ++j){int k = 0;for (; k < 26; ++k){if (flags[i][k] && flags[j][k])break;}
​if (k == 26){int product = words[i].size() * words[j].size();if (product > result)result = product;}}}
​return result;}
};


方法二

方法一是用一个长度为 26 的布尔型数组记录字符串中出现的字符。布尔值只有两种可能,即 true 或 false。这与二进制有些类似,在二进制中数字的每个数位要么是 0 要么是 1。因此,可以将长度为 26 的布尔型数组用 26 个二进制的数位代替,二进制的 0 对应布尔值 false,而 1 对应 true

C++ 中 int 型整数的二进制形式有 32 位,但只需要 26 位就能表示一个字符串中出现的字符,因此可以用一个 int 型整数记录某个字符串中出现的字符。如果字符串中包含 'a',那么整数最右边的数位为 1;如果字符串中包含 'b',那么整数的倒数第 2 位为 1,其余依次类推。这样做的好处是能更快地判断两个字符串是否包含相同的字符。如果两个字符串中包含相同的字符,那么它们对应的整数相同的某个数位都为 1,两个整数的与运算(&)将不会为 0;如果两个字符串没有相同的字符,那么它们对应的整数的与运算的结果等于 0

class Solution {
public:int maxProduct(vector<string>& words) {int length = words.size();vector<int> flags(length, 0);for (int i = 0; i < length; ++i){for (char ch : words[i]){flags[i] |= 1 << (ch - 'a');}}
​int result = 0;for (int i = 0; i < length; ++i){for (int j = i + 1; j < length; ++j){if ((flags[i] & flags[j]) == 0){int product = words[i].size() * words[j].size();if (product > result)result = product;}}}return result;}
};

注意:方法一和方法二的时间复杂度是同一个量级的,但是方法一在判断两个字符串是否包含相同的字符时,可能需要 26 次布尔运算,而方法二只需要 1 次位运算,因此方法二的时间效率更高。

http://www.lryc.cn/news/276090.html

相关文章:

  • 【Java集合篇】HashMap的get方法是如何实现的?
  • Java学习苦旅(二十二)——MapSet
  • 【Linux Shell】12. 文件包含
  • 前端-基础 常用标签-超链接标签( 锚点链接 )
  • 2024--Django平台开发-基础信息(一)
  • C++力扣题目--94,144,145二叉树递归遍历
  • 开源游戏引擎:创造无限可能 | 开源专题 No.56
  • MyBatisPlus学习一:快速入门
  • 2024最新外贸建站:ChemiCloud主机购买使用及自建外贸独立站教程
  • 校招社招,认知能力测验,③如何破解语言常识类测试题?
  • 了解一下InternLM2
  • 关于使用统一服务器,vscode和网页版jupyter notebook的交互问题
  • Linux22.04系统安装显卡驱动,cuda,cudnn流程
  • 【常考简答题】操作系统
  • Large Language Models Paper 分享
  • 微信小程序实战-01翻页时钟-1
  • BigDecimal的性能问题
  • Defi安全-Monox攻击事件Foundry复现
  • 大二上总结和寒假计划
  • 使用 pdfh5 实现 pdf 预览功能
  • HttpRunner辅助函数debugtalk.py
  • PC端扫描小程序二维码登录
  • 计算机毕业设计 | SpringBoot+vue移动端音乐网站 音乐播放器(附源码)
  • Flutter 中的 Stream:异步编程的利器
  • 2023 波卡年度报告选读:Polkadot SDK 与开发者社区
  • 深入了解Go语言中的unsafe.Sizeof():探究变量与数据类型的内存占用
  • 安卓上使用免费的地图OpenStreetMap
  • 基于Java SSM框架实现时间管理系统项目【项目源码+论文说明】
  • Mac安装upx及不同os计算md5值
  • Qt/C++编写视频监控系统82-自定义音柱显示