[LeetCode] 1010. Pairs of Songs With Total Durations Divisible by 60

You are given a list of songs where the ith song has a duration of time[i] seconds.

Return the number of pairs of songs for which their total duration in seconds is divisible by 60. Formally, we want the number of indices ij such that i < j with (time[i] + time[j]) % 60 == 0.

Example 1:

Input: time = [30,20,150,100,40]
Output: 3
Explanation: Three pairs have a total duration divisible by 60:
(time[0] = 30, time[2] = 150): total duration 180
(time[1] = 20, time[3] = 100): total duration 120
(time[1] = 20, time[4] = 40): total duration 60

Example 2:

Input: time = [60,60,60]
Output: 3
Explanation: All three pairs have a total duration of 120, which is divisible by 60.

Constraints:

  • 1 <= time.length <= 6 * 104
  • 1 <= time[i] <= 500

总持续时间可被 60 整除的歌曲。

在歌曲列表中,第 i 首歌曲的持续时间为 time[i] 秒。

返回其总持续时间(以秒为单位)可被 60 整除的歌曲对的数量。形式上,我们希望索引的数字 i 和 j 满足  i < j 且有 (time[i] + time[j]) % 60 == 0。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/pairs-of-songs-with-total-durations-divisible-by-60
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

其实把对60取模这个动作拿掉,你会发现这个题跟two sum几乎是一样的,所以思路也是类似去解决two sum一样的思路。对于两个数相加之后取模的操作,满足如下规则

(A + B) % 60 == (A % 60) + (B % 60)

这里我提供两种实现方式,但是核心思想还是跟two sum类似。

第一种,我们还是创建一个 hashmap,每当遇到一个数字 num 的时候,我们找一下另一个能和当前 num 组成配对的数字是否存在。潜在的配对数字是 (60 - num % 60) % 60。如果有就说明有合法的 pair。这个公式(60 - num % 60) % 60 有一点技巧,处理了两个 corner case,30 + 30 和 0 + 60。注意题目最后说了 1 <= t <= 500,所以 t != 0,但是 t 有可能是 60,所以 comp(第6行)有可能等于 0。如果 comp == 0,hashmap 里是找不到的。如果 t == 30,comp 也等于 30,此时可以与 t 配对的数字的个数也已经存在 hashmap 里了。

时间O(n)

空间O(n)

Java实现

 1 class Solution {
 2     public int numPairsDivisibleBy60(int[] time) {
 3         HashMap<Integer, Integer> map = new HashMap<>();
 4         int res = 0;
 5         for (int t : time) {
 6             int comp = (60 - t % 60) % 60;
 7             res += map.getOrDefault(comp, 0);
 8             map.put(t % 60, map.getOrDefault(t % 60, 0) + 1);
 9         }
10         return res;
11     }
12 }

 

第二种,根据之前解释的关于取模规则的结合律,我们创建一个长度为60的数组,遍历每个数字的时候,对其取模60,然后记录每个数字取模后的结果出现的次数。这里对于取模后结果为0和30的情形要特判,举个例子,如果你遇到0和60,他们各自取模都为0;如果你遇到30和30,他们各自取模都为30。这两种组合的加和都满足题意。其他部分请参见代码。

时间O(n)

空间O(1)

Java实现

 1 class Solution {
 2     public int numPairsDivisibleBy60(int[] time) {
 3         // corner case
 4         if (time == null || time.length == 0) {
 5             return 0;
 6         }
 7 
 8         // normal case
 9         int len = time.length;
10         int[] map = new int[60];
11         int res = 0;
12         for (int i = 0; i < len; i++) {
13             int remainder = time[i] % 60;
14             map[remainder]++;
15         }
16 
17         res += map[0] * (map[0] - 1) / 2;
18         res += map[30] * (map[30] - 1) / 2;
19         for (int i = 1; i < 30; i++) {
20             res += map[i] * map[60 - i];
21         }
22 
23         return res;
24     }
25 }

 

相关题目

1010. Pairs of Songs With Total Durations Divisible by 60

2453. Destroy Sequential Targets

LeetCode 题目总结

posted @ 2020-11-28 05:05  CNoodle  阅读(87)  评论(0编辑  收藏  举报