318. 最大单词长度乘积

318. 最大单词长度乘积

给定一个字符串数组 words,找到 length(word[i]) * length(word[j]) 的最大值,并且这两个单词不含有公共字母。你可以认为每个单词只包含小写字母。如果不存在这样的两个单词,返回 0。

示例 1:

输入: ["abcw","baz","foo","bar","xtfn","abcdef"]
输出: 16 
解释: 这两个单词为 "abcw", "xtfn"

示例 2:

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

示例 3:

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

提示:

  • 2 <= words.length <= 1000
  • 1 <= words[i].length <= 1000
  • words[i] 仅包含小写字母

思路一:最暴力的算法很容易想到是枚举两个串,再遍历两个串看是否有重复字符,复杂度为O(n^2*L)。

思路二:我们注意到数据规模中,n<=1000,L<=1000,因此需要针对n^2或者L优化。直觉上,貌似串的枚举是避免不了的,亦或是很难想到优化,那么我们能不能考虑如何快速判断两个串是否有重复字符呢?

方案1:我们先使用标记数组mark[i]=true表示在字符串A中,已经包含字符 'a' + i,此时再遍历字符串B,如果发现字符串B含有的某个字符的标记为true,那么表明A、B存在相同字符

方案2:由于要看的是是否有重复字符,与字符在哪里无关,因此我们可以事先将字符串内的所有字符排序,然后使用双指针进行判定,即

    当A[p] < B[q]时,令 p++

    当A[p] > B[q]时,令 q++

    当A[p]==B[q]时,找到了重复字符

    否则,p、q任何一个指针超出了字符串范围,则不含有重复字符

    方案2可能可以加速含有重复字符串的判定,但无法加速不含有重复字符的字符串判定

方案3:减少重复计算的思路就是如何利用之前做的计算中所包含的信息,例如,如果A、B之间存在某个相同字符x,且B与C之间存在某个相同字符x,此时就可以根据传递性知道,A、C之间一定有重复字符x,但是这个方案需要考虑的细节很多,编码较为复杂~~

方案4:重新思考方案1,这种哈希的思想是很好的,但是我们用了一个长度为26的数组来存储哈希状态,这就是局限。那么如何根据两个串各自的哈希值判断两个字符串是否有重复?如果能想到位运算,我们将字符串中含有的字符映射为一个26位的二进制数,那么当(hash_A & hash_B) != 0 的时候,表明串A、B存在重复字符。

class Solution {
public:

    int string_hash(string str){
        int res = 0;
        for(int i = str.size() - 1; i >= 0; -- i){
            res |= 1 << (str[i] - 'a');
        }
        return res;
    }

    int maxProduct(vector<string>& words) {
        vector<int> hash_vec, string_len;
        int hash_value, ans = 0, i, j, n = words.size();
        for(string word: words){
            hash_value = string_hash(word);
            hash_vec.push_back(hash_value);
            string_len.push_back(word.length());
        }
        for(i = 0; i < n; ++ i){
            for(j = i + 1; j < n; ++ j){
                if(hash_vec[i] & hash_vec[j]){
                    continue;
                }
                ans = max(ans, string_len[i] * string_len[j]);
            }
        }
        return ans;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值