Trace
7.7 每日一题
传送门:https://leetcode-cn.com/problems/count-good-meals/
Problem
大餐 是指 恰好包含两道不同餐品 的一餐,其美味程度之和等于 2 的幂。
你可以搭配 任意 两道餐品做一顿大餐。
给你一个整数数组 deliciousness
,其中 deliciousness[i]
是第 i
道餐品的美味程度,返回你可以用数组中的餐品做出的不同 大餐 的数量。结果需要对 1e9 + 7
取余。
注意,只要餐品下标不同,就可以认为是不同的餐品,即便它们的美味程度相同。
示例 1:
1 | 输入:deliciousness = [1,3,5,7,9] |
示例 2:
1 | 输入:deliciousness = [1,1,1,3,3,3,7] |
提示:
1 | 1 <= deliciousness.length <= 1e5 |
哈希表
朴素做法,两层循环枚举两个点,判断和是否为2的幂。
优化:判断是否为2的幂,有五种方法。
方法一
求出第一个大于等于$x$的2的幂,然后判断是否等于。
1 | bool check(int x){ |
时间复杂度$O(logx)$。
方法二
思路同方法一,但求第一个大于等于$x$的2的幂时通过位运算实现。
举个栗子,$x=65$,$x-1=64$,二进制表示为$10000000$
$x|=x>>1$,$x=10000000|01000000=11000000$
$x|=x>>2$,$x=11000000|00110000=11110000$
$x|=x>>4$,$x=11110000|00001111=11111111$
之后$x$无改变,二进制表示每一位均变为$1$,$+1$为$128$。
1 | bool check(int x){ |
时间复杂度$O(1)$。
方法三
为$0$时需要特判
1 | bool check(int x){ |
时间复杂度$O(1)$。
方法四
为$0$时需要特判
$ps$:$’==’$优先级比’&’高,所以要加$’()’$,不然结果会出错。
1 | bool check(int x){ |
时间复杂度$O(1)$。
方法五
除此之外此题可以先打表,以便判断是否为2的幂,又$x$最大2的21次幂,所以打到21就好。
1 | unordered_map<int,bool> ump1; |
时间复杂度$O(1)$。
但枚举的时间复杂度为$O(n^2)$,还是会$TLE$,这里只是趁机总结了几种判断一个数是否为2的幂次的方法。
优化:对第二层枚举,可以考虑枚举2的幂,然后判断差是否在数组中,此处可以通过哈希表实现。边插入边统计,保证不会重复计算。
1 | class Solution { |
时间复杂度$O(n*logC)$,$C$为元素值上限。