几乎相同的代码运行速度要慢得多
Posted
技术标签:
【中文标题】几乎相同的代码运行速度要慢得多【英文标题】:Almost same code running much slower 【发布时间】:2016-04-28 13:03:32 【问题描述】:我正在尝试解决这个问题:
给定一个字符串数组words,求length(word[i]) * length(word[j]) 的最大值,其中两个单词不共享共同的字母。您可以假设每个单词只包含小写字母。如果不存在这两个词,则返回0。
https://leetcode.com/problems/maximum-product-of-word-lengths/
您可以为每个单词创建一个 char 位图,以检查它们是否共享 chars,然后计算最大乘积。
我有两个方法差不多,但是第一个通过检查,而第二个太慢,你能理解为什么吗?
class Solution
public:
int maxProduct2(vector<string>& words)
int len = words.size();
int *num = new int[len];
// compute the bit O(n)
for (int i = 0; i < len; i ++)
int k = 0;
for (int j = 0; j < words[i].length(); j ++)
k = k | (1 <<(char)(words[i].at(j)));
num[i] = k;
int c = 0;
// O(n^2)
for (int i = 0; i < len - 1; i ++)
for (int j = i + 1; j < len; j ++)
if ((num[i] & num[j]) == 0) // if no common letters
int x = words[i].length() * words[j].length();
if (x > c)
c = x;
delete []num;
return c;
int maxProduct(vector<string>& words)
vector<int> bitmap(words.size());
for(int i=0;i<words.size();++i)
int k = 0;
for(int j=0;j<words[i].length();++j)
k |= 1 << (char)(words[i][j]);
bitmap[i] = k;
int maxProd = 0;
for(int i=0;i<words.size()-1;++i)
for(int j=i+1;j<words.size();++j)
if ( !(bitmap[i] & bitmap[j]))
int x = words[i].length() * words[j].length();
if ( x > maxProd )
maxProd = x;
return maxProd;
;
为什么第二个函数(maxProduct)对于 leetcode 来说太慢了?
解决方案
第二种方法重复调用words.size()。如果您将其保存在 var 中,则它可以正常工作
【问题讨论】:
好吧,你有一个循环来做(字数)²检查;这将是一个开始...有多少字? 你也称之为位图,但实际上它是一个vector<int>
,而不是由可单独寻址的位组成的东西。
考虑所有单词都有共同字母的情况,并计算每个函数的乘法次数。
@molbdnilo:现在乘法只在 if 之后完成,就像第一个代码一样。但还是太慢了
@MarcusMüller:和第一个差不多(第一个使用数组)
【参考方案1】:
由于我的评论被证明是正确的,我会将我的评论变成答案并尝试解释我认为正在发生的事情。
我编写了一些简单的代码来在我自己的机器上进行基准测试,其中包含两个循环的两个解决方案。唯一的区别是对 words.size() 的调用是在循环内部而不是在循环外部。第一个解决方案大约为 13.87 秒,而第二个解决方案为 16.65 秒。这不是很大,但速度会慢 20%。
尽管 vector.size() 是一个恒定时间操作,但这并不意味着它与检查寄存器中已经存在的变量一样快。恒定时间仍然可以有很大的差异。在加起来的嵌套循环内时。
可能发生的另一件事(比我聪明得多的人可能会插话并让我们知道)是您正在损害您的 CPU 优化,例如分支和流水线。每次到达循环结束时,它必须停止,等待对 size() 的调用返回,然后根据该返回值检查循环变量。如果 CPU 可以向前看并猜测 j
仍然会小于 len
,因为它没有看到 len
发生变化(len
甚至不在循环内!)每次都进行分支预测,无需等待。
【讨论】:
不确定你是如何测试它的,但是vector
版本零初始化bitmap
,而另一个缓冲区在分配之前未初始化。
@jarod42 我用一个我在计时之前初始化的向量进行了测试,然后对两组相同的两个循环进行了计时,唯一的区别是.size()
是在比较中或完成一次第一的。第二个循环速度较慢,尽管它具有在同一个向量上第二个并做同样事情的优势。以上是关于几乎相同的代码运行速度要慢得多的主要内容,如果未能解决你的问题,请参考以下文章