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

来源:互联网 发布:linux tar只读权限 编辑:程序博客网 时间:2024/05/30 04:46

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
原创粉丝点击