通关剑指Offer——剑指 Offer II 005. 单词长度的最大乘积

1.题目描述

剑指 Offer II 005. 单词长度的最大乘积

给定一个字符串数组 words,请计算当两个字符串 words[i] 和 words[j] 不包含相同字符时,它们长度的乘积的最大值。假设字符串中只包含英语的小写字母。如果没有不包含相同字符的一对字符串,返回 0。

示例 1:

输入: words = ["abcw","baz","foo","bar","fxyz","abcdef"]
输出: 16 
解释: 这两个单词为 "abcw", "fxyz"。它们不包含相同字符,且长度的乘积最大。

示例 2:

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

示例 3:

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

2.解题思路与代码

2.1 解题思路

首先要确定一个单词里面出现了那些字母,然后再依次比较单词中出现的字母是否重复,那么这里就可以考虑使用位运算来解答。我们知道一个 int 整数是 32 位的,而小写字母共 26 位,那么我们就可以使用整型的 26 位来分别表示从 a 到 z 的字母是否出现:0 表示没有出现,1 表示出现。以 “abc” 为例,首先我们初始化一个 num1=0,这个时候 num1 的每一位都为 0.

然后我们开始遍历 “abc” ,第一位取到 ‘a’ ,将 num1 上的位数从 0 开始依次表示字母 a 到 z ,因此字母 a 所在的位置是在 ‘a’-‘a’ 第 0 位,于是使用 1 左移 0 位并与 num1 进行或运算将第 0 位 1 赋值给 num1

之后遍历到 b,此时 b 应当在第 1 位,于是将 1 左移 1 位后再与 num1 或运算,如下图所示

同理遍历对 c 进行处理

此时我们将 a、b、c 三个字母是否出现定义给了 num1 的前三位。同理我们对 “xyz” 进行赋值得到 num2,得到下图

在得到每个单词的字幕出现情况之后,便可以通过与运算比较两个单词中是否有重复字母。例如我们要比较 “abc” 和 “xyz” 是否包含重复字母,直接将 num1 和 num2 按位与运算,由于与运算都为 1 才是 1 ,那么如果每一位都不同,那么必然结果为 0 ,如果不为 0 那么一定存在重复字母。

2.2 代码

class Solution {
    public int maxProduct(String[] words) {
        int n = words.length;
        int[] tmp = new int[n];
        for (int i = 0; i < n; i++) {
            int num = 0;
            for (int j = 0; j < words[i].length(); j++) {
                // 通过位运算记录字母是否出现
                num |= 1 << (words[i].charAt(j) - 'a');
            }
            tmp[i] = num;
        }
        int max = 0;
        for (int i = 0; i < n - 1; i++) {
            for (int j = i + 1; j < n; j++) {
                // 依次求与运算,如果结果等于零表示两个单词没有重复字母,此时计算长度乘积最大值
                if ((tmp[i] & tmp[j]) == 0) {
                    max = Math.max(max, words[i].length() * words[j].length());
                }
            }
        }
        return max;
    }
}

2.3 测试结果

通过测试

测试结果

3.总结

  • 首先使用位来记录单词中字母出现情况
  • 依次按位求与运算, 如果结果是 0 表示两个单词中没有相同字母;不为 0 表示一定有相同字母
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值