一、题目描述

二、问题代码
class solution{
public int numPairsDivisibleBy60(int[] time) {
int count = 0;
for(int i = 0;i<time.length;i++){
for(int j = i+1;j<time.length;j++){
if((time[i]+time[j])%60 ==0){
count++;
}
}
}
return count;
}
}
三、存在的问题
- 时间复杂度为 O(n^2);
- 测试用例成功,但提交失败;
- 逻辑暴力,但仍未成功。
四、切换思路
- 尝试使用双指针解决。
int l = 0;
int r = time.length -1;
while(l<r){
if((time[i]+time[j])%60 ==0 ){
count++;
left++;
}else{
right--;
}
}
- 逻辑漏洞太大了,首先,即使找到复合条件的两个元素,left也不应该自加,因为依然可能存在和left索引指向元素相加满足条件的元素;
- 去掉
left++后,没有控制left自加合适的条件。
四、题目解析
如果单纯地计算两个元素只和是否为60的整数倍,需要判断的情况太多。
- 取余函数可以将数组元素限定在[0,59]之内;
- 使用元素索引当作余数,元素索引指向值作为余数出现次数;
- 两个元素的余数相加等于60,满足题目条件;
- 当余数为0或30的元素,需要在自身的数目中查找;
五、优解代码
class Solution{
public int numPairsDivisibleBy60(int[] time) {
int count =0;
int[] remainder = new int[60];
for(int t : time){
remainder[t % 60]++;
}
for(int i=1;i<30;i++){
count += remainder[i]*remainder[60-i];
}
count += remainder[0]*(remainder[0]-1)/2;
count += remainder[30]*(remainder[30]-1)/2;
return count;
}
}
六、优解特点
- 使用索引表示余数,使用索引对应值表示余数出现次数;
- 注意考虑余数为0,30的情况;
- 两次遍历。