zoukankan      html  css  js  c++  java
  • Maximum Product of Word Lengths -- LeetCode

    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.

    思路:朴素的方法是O(n^2),我们可以在这个基础上进行剪枝。

    这个题目有两个技巧:一个是如何最快地判断两个字符串是否含有相同的字符,另一个是如何进行剪枝。

    位运算判断相同字符:

    对于给的每一个字符串,我们用一个int变量来存储它的字符分布。由于给的字符串只含有26个小写字母,我们只需要26位就能存储下来(若某个字母出现,就将对应的位置为1,否则为0)。当我们需要判断两个字符串是否含有相同的字符时,只需将对应的两个int变量进行与运算,若结果为0则不含有相同字符,否则就是有。

    剪枝:

    将给的所有字符串按照长度进行排序。

    调用stl的sort函数时,我们需要重新定义比较函数。当比较函数在类内部定义时,要定义为静态函数。或者直接定义为全局函数。因此leetcode对静态函数支持不好,所以我用全局函数来实现。

    我们先从最后两个字符串进行考虑,因为这两个的长度乘积是所有可能中最大的。

    我们用两个指针来指向他们:假设i是最后一个字符串,j是倒数第二个。

    我们将j依次向前移动,直到字符串i和j不含有重复字符。

    记录下此时两个字符串长度的乘积,用res来表示。然后j不再需要进行前移,因为再往前j所指向的字符串的长度只会变小,不可能获得更大的结果。

    此时,唯一可能产生更大结果的情况是:存在两个字符串m和n,它们的下标构成关系j < m < n < i。可以看到,这时m和n的字符串长度都不小于j,因此两者的乘积有可能会大于当前的结果。这里我们用floor来表示j所在的位置。

    因此我们将i前移一位,然后j指向i-1的位置继续重复这个步骤。不过这里,j只需要前移到floor+1 (上一次找到结果时j所在位置的下一位)的位置。因为,上一次找到结果时,j所在的位置为floor,这一次如果j指向了floor或者更前的位置,则两个字符串的乘积一定比之前的结果要小,因为j和i指向的字符串的长度都比之前要短了。

     1 bool shorter(const string& a, const string& b)
     2 {
     3     return a.size() < b.size();
     4 }
     5 class Solution {
     6 public:
     7     int maxProduct(vector<string>& words) {
     8         sort(words.begin(), words.end(), shorter);
     9         vector<int> dict(words.size());
    10         for (int i = 0, n = words.size(); i < n; i++)
    11             for (int j = 0, len = words[i].size(); j < len; j++)
    12                 dict[i] |= (1 << (int)(words[i][j] - 'a'));
    13         int floor = -1, res = 0;
    14         for (int i = words.size() - 1; i > floor; i--)
    15             for (int j = i - 1; j > floor; j--)
    16                 if (!(dict[i] & dict[j]))
    17                 {
    18                     int l1 = words[i].size(), l2 = words[j].size();
    19                     res = max(res, l1 * l2);
    20                     floor = j;
    21                     break;
    22                 }
    23         return res;
    24     }
    25 };
  • 相关阅读:
    docker tar 镜像 容器相互转换
    JavaScript执行上下文
    JavaScript 作用域
    原型与原型链
    使用Navicat for Oracle新建表空间、用户及权限赋予
    PL/SQL Developer使用教程(中文)
    一步一步使用bootstrap开发一个博客模板
    How to create a simple blog using ASP.NET MVC
    一个有意思的编程网站
    一个很好的java编程国外网站
  • 原文地址:https://www.cnblogs.com/fenshen371/p/5138201.html
Copyright © 2011-2022 走看看