【LeetCode】1010. Pairs of Songs With Total Durations Divisible by 60

题目

https://leetcode.com/problems/pairs-of-songs-with-total-durations-divisible-by-60/

In a list of songs, the i-th 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 i < j with (time[i] + time[j]) % 60 == 0.

Example 1:
Input: [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: [60,60,60]
Output: 3
Explanation: All three pairs have a total duration of 120, which is divisible by 60.
 

Note:

1 <= time.length <= 60000
1 <= time[i] <= 500

题意

题目的意思是找出数组中两数之和能被60整除的数对,数组最大的长度是60000,如果使用暴力求解需要两层循环,需要进行59999+5998+…+2+1=1799910001次计算和判断的,很显然会超时。

代码

做的时候头脑里总感觉想到点东西,但就是想不出来,然后就去找了一下别人的解法。代码比较短,但是思路是比较精妙的,可以这样理解:

  • 首先,两数相加的和能被60整除,也就是两数除60的余数相加和为60,因此可以将问题规模压缩的60,如何压缩?请看下面
  • 设定一个数组occured,表示0-59这60个余数出现出现的此时,比如occured[1]=3表示除60余数为1的数目前已经出现过三次
  • 这个occured的作用是什么呢?在遍历的时候我们不管遍历的当前数字和哪些数字能够匹配(也就是不需要一层循环来往后找和当前数字匹配的数),只需要去occured数组里获取能和当前数字匹配的数字(除60后余数相加等于60,在代码中匹配的余数就是60 - time[i])出现过多少次
  • 另外这个出现过多少次怎么记录?就是在遍历到当前数字时,将occured数组对应其余数位置的值+1,标记已经出现过了。比如:[1,61,121]在找到1时occured[1 % 60] = occured[1] = 1,找到61时occured[61 % 60] = occured[1] = 2,找到121时occured[121 % 60] = occured[1] = 3

具体代码如下

class Solution {
    public int numPairsDivisibleBy60(int[] time) {
        int result = 0;
        int[] occured = new int[60];

        for(int i = 0;i < time.length;i++){
            time[i] %= 60;
            int index = time[i] == 0 ? 0 : 60 - time[i];
            result += occured[index];
            occured[time[i]]++;
        }
        
        return result;
    }
}

参考:https://blog.csdn.net/qq_44946782/article/details/89410325

你可能感兴趣的:(算法,Java)