每日一题-数组 *leetcode1010

211 阅读1分钟

一、题目描述

二、问题代码

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;
    }
}

三、存在的问题

  1. 时间复杂度为 O(n^2);
  2. 测试用例成功,但提交失败;
  3. 逻辑暴力,但仍未成功。

四、切换思路

  1. 尝试使用双指针解决。
int l = 0;
int r = time.length -1;
while(l<r){
    if((time[i]+time[j])%60 ==0 ){
        count++;
        left++;
    }else{
        right--;
    }
}
  1. 逻辑漏洞太大了,首先,即使找到复合条件的两个元素,left也不应该自加,因为依然可能存在和left索引指向元素相加满足条件的元素;
  2. 去掉left++后,没有控制left自加合适的条件。

四、题目解析

如果单纯地计算两个元素只和是否为60的整数倍,需要判断的情况太多。

  1. 取余函数可以将数组元素限定在[0,59]之内;
  2. 使用元素索引当作余数,元素索引指向值作为余数出现次数;
  3. 两个元素的余数相加等于60,满足题目条件;
  4. 当余数为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;
    }
}

六、优解特点

  1. 使用索引表示余数,使用索引对应值表示余数出现次数;
  2. 注意考虑余数为0,30的情况;
  3. 两次遍历。