1010. 总持续时间可被 60 整除的歌曲(简单)- LeetCode

题目描述

在这里插入图片描述

自己解法

思路:本问题中,我们不关心数组的值,只关心满足条件的次数,所以可以对原数组进行修改。需要意识到的一个规律是:如果两个数 a , b a,b a,b相加能被60整除,那么(a%60) + (b%60) = 60,所以我们可以利用这个规律来简化杂乱的初始数组,将数组值范围约束在0~59

步骤:首先对初始列表的所有元素取余(%)60,元素都落在0~59范围内。建立一个字典time_dict,键的取值范围是0~59(可能只包含部分数字),值是键在原数组中出现的次数。针对字典中键的分布,有两种情况,分别用ans_1,ans_2来存储:

  • 如果键是0或30,键的特点是它们内部两两成对,当值val大于1时,ans_1的值等于val*(val-1)/2(组合数公式)
  • 其他情况即1~29,31~59,键的特点是与对称位置(如1与59)键凑成一对,对于当前key,如果60-key也存在于字典的键中,那么ans_2的值等于这两个键对应的值相乘,循环结束ans_2要除以2,因为对称的部分算了2次。

复杂度分析:

  • 时间复杂度: O ( n ) O(n) O(n),对长度为 n n n的初始数组要做 n n n次取余操作;
  • 空间复杂度: O ( 1 ) O(1) O(1),ans_1,ans_2,time_dict的长度不会随 n n n变化。
class Solution:
    def numPairsDivisibleBy60(self, time: List[int]) -> int:
        for i in range(len(time)):
            time[i] %= 60
        time_dict = {}
        ans_1,ans_2 = 0,0

        for val in time:
            if val in time_dict.keys():
                time_dict[val] += 1
            else:
                time_dict[val] = 1

        for key,val in time_dict.items():
            if (key == 0 or key == 30) and val > 1:
                    ans_1 += val*(val-1)/2
            else:
                if 60-key in time_dict.keys():
                    ans_2 += val * time_dict[60-key]
        return int(ans_1 + ans_2/2)

在这里插入图片描述

题解区解法

参考链接:Java 【2ms 击败100.00%】

思路和我的一样,都是利用余数规律,不同之处是直接开了一个长度为60的数组,与我的方法对比,坏处是存储空间变大,因为字典键的范围可能没有覆盖0~59,数组长度固定为60,好处是后续遍历对称位置的键值很方便,时间性能好,Java代码:

	public int numPairsDivisibleBy60(int[] time) {
		int count = 0;
		int[] seconds = new int[60];
		for(int t : time) {
			seconds[t % 60] += 1; 
		}
		count += combination(seconds[30], 2);
		count += combination(seconds[0], 2);
		int i = 1, j = 59;
		while(i < j) {
			count += seconds[i++] * seconds[j--];
		}
		return count;
	}
	
	// 求组合数
	public int combination(int n, int k) {
		long result = 1;
		for(int i = 1; i <= k; i++) {
			result = result * (n - i + 1) / i;
		}
		return (int)result;
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值