我遇到了以下问题。
给出一个列表,其中每个项目代表以歌曲的秒数表示的持续时间,返回成对的歌曲总数,这样它们的持续时间总计为分钟(例如1m0s,2m0s等)。
示例:
输入:[10,50,20,110,40]
输出:3(考虑索引为(0,1),(0,3),(2,4)的对)
我只能考虑一种蛮力的方法,在这种方法中我要考虑所有的歌曲对。这种方法的时间复杂度为O(n ^ 2)。
有更好的方法吗?
答案 0 :(得分:1)
(a,b)
,以便从给定列表A中找到(a + b) mod 60 == 0
。初始化一个长度为60的数组,其默认值设置为0,其索引 i 将存储列表A中的元素数,使得所有元素的x mod 60 = i
x属于A
int freq[60] = {0};
for(int i = 0; i < A.size(); i++)
freq[(A[i] % 60)]++;
现在再次遍历数组A,对于每个x,我们需要从累积频率图中获取索引60 - (x mod 60)
的计数,该计数对应于它可以形成一对的元素的数量用。在(x mod 60) == 30
会很棘手的情况下,这将要求我们从频率计数中减去1。
int ans = 0;
for(int i = 0; i < A.size(); i++) {
ans += freq[60 - (A[i] % 60)];
if(A[i] % 60 == 30) ans--;
}
解决方案的整体复杂度为O(n)。
答案 1 :(得分:0)
考虑一下散列,创建存储桶和模除的行。所有可能的分钟数将进入60个可能的存储桶之一。然后考虑从任意两个存储桶中选择两个第二个值时可能有多少种组合。然后使用nC2进行计数。这是我在Java中的解决方案。
public int numPairsDivisibleBy60(int[] time) {
int k = 60;
int[] mods = new int[k];
for (int i = 0; i < time.length; i++)
mods[time[i] % k]++;
// n(n-1)/2 pairs for multiples of k and numbers which leave remainder as half multiple of k
int count = ((mods[0] * (mods[0] - 1)) / 2) +
((mods[k / 2] * (mods[k / 2] - 1)) / 2);
for (int i = 1; i < k / 2; i++)
count += mods[i] * mods[k - i];
return count;
}