问题
有一个歌曲列表,第i
首歌有time[t]
的时长。返回成对歌曲的数量,要求它们时长之和能被60
整除。即i < j,(time[i] + time[j]) % 60 = 0
。
栗子1:
输入:[30,20,150,100,40]
输出:3
匹配结果:
30-150、20-100、20-40
栗子2:
输入:[60,60,60]
输出:3
匹配结果:
60-60、60-60、60-60
注意:
1 <= time.length <= 60000
1 <= time[i] <= 500
想看英文的戳这里:原题地址
解题思路
很容易想到的是两层 for
循环,但既然题目出在这了,自然不可能是暴力循环法。所以需要从 % 60
上面来思考。
如果 (x + y) % 60 = 0
,则 x % 60 = 60 - y % 60
,其实这个规则就是最主要的解题思路。
而 x % 60
的范围是[0, 59]
,60 - y % 60
的范围是[0, 60]
。所以为了使两者取值范围相等,需要将后者%60
,即x % 60 = (60 - y % 60) % 60
。
所以当我们遇到某个数t
时,只需要计算公式左边的值的个数
有几个,则有几对。
举个栗子,比如time = [20, 40, 100, 80]
。
- 遇到
20
,套用公式右边计算出与之匹配的数%60
的结果60 - y % 60 = 40
。因为是第一个数,无与之匹配的。 - 遇到
40
,与之匹配的数%60
的结果 为20
,存在20
, 共1
个。 - 遇到
100
, 与之匹配的数%60
的结果 为20
,存在20
, 共1
个。 - 遇到
80
,与之匹配的数%60
的结果为40
,存在40,100
,共2
个。
所以我们可以用数组array
存 t % 60
出现的个数,遍历time
数组,直接取出array[(60 - t % 60) % 60]
即为匹配的对数。
swift
代码如下:
func numPairsDivisibleBy60(_ time: [Int]) -> Int {
var count = 0
var array = [Int]()
var i = 0
while i < 60 {
// 初始化为 0
array.append(0)
i += 1
}
for t in time {
count += array[(60 - t % 60) % 60]
// 次数加1
array[t % 60] += 1
}
return count
}