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

原题地址:剑指 Offer II 005. 单词长度的最大乘积

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

直接遍历

    public int maxProduct(String[] words) {
        int res = 0;
        int n = words.length;
        for (int i = 0; i < n; i++) {
            String A = words[i];
            for (int j = 0; j < n; j++) {
                String B = words[j];
                if (!helpWord(A, B)) res = Math.max(res, (A.length() * B.length()));
            }
        }
        return res;
    }

    // 两个字符串之间是否存在公共字符
    public boolean helpWord(String A, String B) {
        for (char c : A.toCharArray()) {
            // indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置
            // 如果没有找到匹配的字符串则返回 -1
            if (B.indexOf(c) != -1) return true;
        }
        return false;
    }

此方法为暴力解法,直接遍历比对两个字符串之间是否存在相同的公共字符。leetcode的用例此方法会超时

位运算

    public int maxProduct(String[] words) {
        int n = words.length;
        // 存储将原本的数组转为二进制后的新数组
        // 将字符串中字符出现情况用二进制数表示,即字符a~z对应二进制数第0~25位,
        // 哪个字符出现就将二进制数对应位置1。这样的话对于不含相同字符的字符串,
        // 它们的二进制表示进行与运算结果就为0,否则结果就不为0,位运算能大大加快算法速度。
        int[] binaryBit = new int[n];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < words[i].length(); j++) {
                // binaryBit[i]用数字的二进制表示来记录words[i]包含的字母
                // 有字母则其在字母表对应位的数字二进制该位置为1,不存在的字母为0。
                binaryBit[i] |= (1 << (words[i].charAt(j) - 'a'));
            }
        }
        int res = 0;
        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                // 如果i、j单词对应的二进制某一位有都为1,则说明该位置表示的字母二者都有
                // 否则若binaryBit[i]&binaryBit[j]==0,说明两个单词没有重复字母,可以计算乘积。
                // 与运算中:1&1=1
                if ((binaryBit[i] & binaryBit[j]) == 0) res = Math.max(res, words[i].length() * words[j].length());
            }
        }
        return res;
    }

将原来的每个单词转换为二进制,单词对应的二进制中,某一位为0表示这一位的字母没有出现,为1则表示出现。然后通过对两个单词的二进制进行位运算(位运算中只有1&1=1)可以快速区别两个单词之间是否存在公共字符,节省时间效率。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值