1711. 大餐计数-每日一题

一、题目

  大餐 是指 恰好包含两道不同餐品 的一餐,其美味程度之和等于 2 的幂。

  你可以搭配 任意 两道餐品做一顿大餐。

  给你一个整数数组 deliciousness ,其中 deliciousness[i] 是第 i道餐品的美味程度,返回你可以用数组中的餐品做出的不同 大餐 的数量。结果需要对 10^9 + 7取余。

  注意,只要餐品下标不同,就可以认为是不同的餐品,即便它们的美味程度相同。

点击查看原题
难度级别: 中等

二、思路

1)哈希表

  直接想到暴力法的求解,就是使用O(n^2)时间复杂度进行遍历,把所有的组合都遍历一遍,就可以找到总的组合数量
  为了减小时间复杂度,使用一个hashmap来寻找在遍历过的数中,是否存在一个数与当前数之和为2的幂次方hashmap中的键为美味程度数值,值为已经遍历的同美味程度菜肴数量;且两数之和小于等于最大值*2

三、代码

1)哈希表

class Solution {
    public int countPairs(int[] deliciousness) {
        long ans = 0;
        Map<Integer, Integer> memo = new HashMap();
        int maxVal = 0;
        for (int i : deliciousness) {	// 找到最大值
            maxVal = Math.max(maxVal, i);
        }
        maxVal <<= 1;
        for (int val : deliciousness) {
            for (int i = 1; i <= maxVal; i <<= 1) {
                if (i < val) {	// 本题两个数之和一定大于或等于单独数值的
                    continue;
                }
                int needVal = i - val;
                ans = (ans + (long)memo.getOrDefault(needVal, 0)) %1000000007;
            }
            memo.put(val, memo.getOrDefault(val, 0) + 1);
        }
        return (int)ans;
    }
}

  时间复杂度为O(nlogC)C为最大值上限,空间复杂度为O(n)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

佳鑫大大

你的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值