LeetCode 318. Maximum Product of Word Lengths解题记录

1. 题目描述

https://leetcode.com/problems/maximum-product-of-word-lengths/#/description

Given a string array words, find the maximum value of length(word[i]) * length(word[j]) where the two words do not share common letters. You may assume that each word will contain only lower case letters. If no such two words exist, return 0.
Example 1:
Given [“abcw”, “baz”, “foo”, “bar”, “xtfn”, “abcdef”]
Return 16

The two words can be “abcw”, “xtfn”.
Example 2:
Given [“a”, “ab”, “abc”, “d”, “cd”, “bcd”, “abcd”]
Return 4
The two words can be “ab”, “cd”.

Example 3:
Given [“a”, “aa”, “aaa”, “aaaa”]
Return 0
No such pair of words.

Credits:
Special thanks to @dietpepsi for adding this problem and creating all test cases.
Subscribe to see which companies asked this question.

2. 题目分析

其实通过分析题干,我们就已经获取的得到了处理这个题目的基本思路了

for i in words:
    for j in words:
        if (words[i], words[j] 没有公共部分):
            统计最大乘积长度

3. 代码展示

3.1 first-version

按照上面描述的这个思路,我们给出下面代码:

class Solution {
public:
    int maxProduct(vector<string>& words) {
        size_t wordSize = words.size();
        if (wordSize < 2)
            return 0;

        int maxProductValue = 0;
        for (size_t i = 0; i < wordSize; i++){
            for (size_t j = i + 1; j < wordSize; j++){
                if (!hasCommonElement(words[i], words[j])){
                    int productVelue = words[i].length() * words[j].length();
                    if (maxProductValue < productVelue){
                        maxProductValue = productVelue;
                    }
                }                   
            }
        }
        return maxProductValue;
    }

private:
    bool hasCommonElement(const string & a, const string & b) const{
        auto bitseta = convertStringToBitset(a);
        auto bitsetb = convertStringToBitset(b);
        auto bitsetCommon = (bitseta & bitsetb);
        return bitsetCommon.any();
    }

    bitset<26> convertStringToBitset(const string & str) const{
        bitset<26> stringa;
        for (size_t i = 0; i < str.length(); i++){
            if (!stringa.test(str.at(i) - 'a'))
                stringa.set(str.at(i) - 'a');
        }
        return stringa;
    }
};

运行结果:
这里写图片描述

3.2 second-version

这个运行效率,感觉不能忍受啊,怎么这么慢,通过分析,我们发现,程序在hasCommentElement这个子函数中的调用非常耗时, 通过分析代码,我们可以知道,实际上对每个word只要执行一次, ie, O(n) 的 convertStringToBitset被执行了 O(n2) 量级次,因而由此表现出来的效果就体现在了这个时间效率上
这里写图片描述
这里写图片描述
于是,我们可以通过把这部分公共转换提取到外围去得到如下代码:

class Solution {
public:
    int maxProduct(vector<string>& words) {
        size_t wordSize = words.size();
        if (wordSize < 2)
            return 0;

        vector<bitset<26>> bitsetArray;
        for (size_t i = 0; i < wordSize; i++){
            bitsetArray.emplace_back(convertStringToBitset(words[i]));
        }

        int maxProductValue = 0;
        for (size_t i = 0; i < wordSize; i++){
            for (size_t j = i + 1; j < wordSize; j++){
                if (!hasCommonElement(bitsetArray[i], bitsetArray[j])){
                    int productVelue = words[i].length() * words[j].length();
                    if (maxProductValue < productVelue){
                        maxProductValue = productVelue;
                    }
                }
            }
        }
        return maxProductValue;
    }

private:
    inline bool hasCommonElement(const bitset<26> & bitseta, const bitset<26> & bitsetb) const{
        auto bitsetCommon = (bitseta & bitsetb);
        return bitsetCommon.any();
    }

    bitset<26> convertStringToBitset(const string & str) const{
        bitset<26> stringa;
        for (size_t i = 0; i < str.length(); i++){
            if (!stringa.test(str.at(i) - 'a'))
                stringa.set(str.at(i) - 'a');
        }
        return stringa;
    }
};

此时代码执行效果为:
这里写图片描述
运行效率立马得到了显著的提升,然而,本质上我们这个算法的时间复杂度还是处于 O(n2) 量级的

4. 参考解法

https://discuss.leetcode.com/topic/31766/bit-shorter-c
这个解法的基本思想是使用hash表,将代码的时间复杂度控制在 O(n) 的量级, 链接中的讨论主要在纠结为什么这个复杂度是 O(n) 而不是 O(n2) , 这是因为我们所构建的hash表的第一项本质上是一个 26bit 长度的位图,在最差情况下,hash表的长度只有 226 , 这个数字虽然很大,但是根据他实际上只是以个很大的常数,因而算法复杂度还是在 O(n) 的量级。

int maxProduct(vector<string>& words) {
    vector<int> mask(words.size());
    int result = 0;
    for (int i=0; i<words.size(); ++i) {
        for (char c : words[i])
            mask[i] |= 1 << (c - 'a');
        for (int j=0; j<i; ++j)
            if (!(mask[i] & mask[j]))
                result = max(result, int(words[i].size() * words[j].size()));
    }
    return result;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值