Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用字典中没有共同字母的成对单词,找到一对最大化单词总和的单词';长度_Java_String_Algorithm_Dictionary - Fatal编程技术网

Java 使用字典中没有共同字母的成对单词,找到一对最大化单词总和的单词';长度

Java 使用字典中没有共同字母的成对单词,找到一对最大化单词总和的单词';长度,java,string,algorithm,dictionary,Java,String,Algorithm,Dictionary,问题: 使用字典中没有共同字母的成对单词,查找 使单词长度之和最大化的一对 示例字典:鼠标、牛、连接、键、狗 狗和键不共享字母,总和为3+3=6 鼠标不能与奶牛、加入或狗一起使用,因为它们都使用字母“o” join和key不共享字母,且总和为4+3=7 我在一次采访中提出了这个问题,我提出的解决方案概述如下。我想知道是否有什么方法可以提高效率?我使用了两个位集来映射两个单词的字母表,并将它们放在一起查看它们是否包含相同的字母。我认为我的算法的复杂度是o(n!),这是低效的,有没有更好的方法来优化

问题:

使用字典中没有共同字母的成对单词,查找 使单词长度之和最大化的一对

示例字典:鼠标、牛、连接、键、狗

不共享字母,总和为3+3=6

鼠标不能与奶牛加入一起使用,因为它们都使用字母“o”

joinkey不共享字母,且总和为4+3=7

我在一次采访中提出了这个问题,我提出的解决方案概述如下。我想知道是否有什么方法可以提高效率?我使用了两个
位集
来映射两个单词的字母表,并将它们放在一起查看它们是否包含相同的字母。我认为我的算法的复杂度是o(n!),这是低效的,有没有更好的方法来优化我的算法

public static void maximumSum (String[] dictionary) {
    // ascii of a = 97
    BitSet word1 = new BitSet(26);
    BitSet word2 = new BitSet(26);

    String maxWord1 = "";
    String maxWord2 = "";
    int maxSum = -1;

    for(int i = 0; i<dictionary.length; i++) {
        for(int j = i+1; j<dictionary.length; j++) {
            String s1 = dictionary[i];
            String s2 = dictionary[j];
            for(int k = 0; k<s1.length(); k++) {
                word1.set(s1.charAt(k)-97);
            }
            for(int k = 0; k<s2.length(); k++) {
                word2.set(s2.charAt(k)-97);
            }
            word1.and(word2);
            if(word1.cardinality() == 0) {
                if(maxSum < s1.length()+s2.length()) {
                    maxWord1 = s1;
                    maxWord2 = s2;
                    maxSum = s1.length()+s2.length();
                }
            }
            word1.clear();
            word2.clear();
        }
    }
    if(maxSum == -1)
        System.out.println("All the words have letters in common.");
    else
        System.out.println("'"+maxWord1+"' and '"+maxWord2+"' 
        have a maximum sum of "+maxSum);
}

public static void main(String[] args) {
    String[] dictionary = {"mouse", "cow", "join", "key", "dog"};
    maximumSum(dictionary);
}
你可以用O(N^2*26)来表示(26代表字典中的字符数,可能是英语字母)

首先 构建一个二维布尔数组,D[i][j]

i-整数

j-字符从“a”到“z”(您可以使用ASCII码而不是字符)

如果索引i处的单词包含字母j,则D[i][j]=1,否则D[i][j]=0


拥有这个2D数组后,您可以检查每一对单词是否有一个共同的字母(您迭代字典中的每一对单词和每个字母)。如果他们不这样做,你就实现了最大的总和。

这里有一种方法可以称为
O(n*avg)
,尽管它可能应该称为
O(n*avg+a*2^a)
,其中a是字母表的大小,n是单词的数量,avg是字典中单词的平均长度,以防你可以用更大的字母表来做这件事。如果你的字典只有几千个单词,那么它不会比Bogdan Pop提到的暴力方法有所改进,但是当字典包含数十万个单词时,它将是一种改进。相比之下,一些竞争性拼字游戏玩家使用的拼字游戏包含超过267000个单词。在最后一段之前,这一方法的大部分基本上与其他方法相同

对于每个单词w,确定其长度l(w)以及包含哪些字母s(w)

对于字母表的每个2^a子集,通过迭代每个单词w,并用其自身和l(w)的最大值替换存储在s(w)中的长度,确定恰好包含这些字母的最长单词

对于字母表的每个2^a子集,确定最多包含这些字母的最长单词。这可以在
O(a*2^a)
步骤中完成,因为大小为k的每个子集包含k个较小的子集,其中包含k-1个字母。我们以归纳的方式计算该值,即恰好包含这些字母或包含在其中一个k-1覆盖子集中的最长单词

现在我们可以迭代字母表的所有子集,使用这些字母和该子集补码中包含的最长单词的长度求和


这种方法的一个不令人满意的部分是,由于包含了不常见的字母,时间增加了很多。由于Q、X、J和Z,所用的时间大约增加了20倍,这在一般的单词中并不常见,我认为在长单词中也不常见。因此,假设有r个单词至少包含b个罕见字母中的一个。我们可以对
O(n*avg+(a-b)2^(a-b))
步骤中没有稀有字母的单词使用上述算法。然后,我们可以在
O(r^2*a)
步骤中对包含罕见字母的单词对进行暴力处理。最后,我们可以通过遍历包含稀有字母的r个单词来检查第一个包含稀有字母但第二个不包含稀有字母的单词对,检查补码中只有普通字母的最长单词。最后一种情况需要
O(r*avg)
步数,因此其渐近可忽略不计。因此,通过选择几个罕见的字母,我们可以将时间缩短到
O(n*avg+(a-b)2^(a-b)+r^2*avg)
。至少,在一本标准的英语词典中,很少使用字母,所以这将是一种减少。

我不知道你为什么说o(n!)。对于蛮力方法,您的算法效率有点低,但它是O(n^2 avg(length)),其中avg(length)表示字典中一个单词的平均长度。正如博格丹·波普所回答的那样,只需计算一次每个单词的内容,就可以非常轻松地提高效率。应该有比暴力更好的方法,但n^2比n!好得多!。这是关于Quora的同样问题:谢谢!我不太确定其复杂性,谢谢你澄清了这一点。嗯,如果一个字母可能在一个单词中重复-它会改变最佳方法:
join
keyyyyyyyy
不共享字母,但长度超过
join
key
'join' and 'key' have a maximum sum of 7