前言
经过前期的基础训练以及部分实战练习,粗略掌握了各种题型的解题思路。现阶段开始专项练习。
描述
给你一个正整数
n
,你需要找到一个下标从 0 开始的数组powers
,它包含 最少 数目的2
的幂,且它们的和为n
。powers
数组是 非递减 顺序的。根据前面描述,构造powers
数组的方法是唯一的。同时给你一个下标从 0 开始的二维整数数组
queries
,其中queries[i] = [lefti, righti]
,其中queries[i]
表示请你求出满足lefti <= j <= righti
的所有powers[j]
的乘积。请你返回一个数组
answers
,长度与queries
的长度相同,其中answers[i]
是第i
个查询的答案。由于查询的结果可能非常大,请你将每个answers[i]
都对109 + 7
取余 。示例 1:
输入:n = 15, queries = [[0,1],[2,2],[0,3]] 输出:[2,4,64] 解释: 对于 n = 15 ,得到 powers = [1,2,4,8] 。没法得到元素数目更少的数组。 第 1 个查询的答案:powers[0] * powers[1] = 1 * 2 = 2 。 第 2 个查询的答案:powers[2] = 4 。 第 3 个查询的答案:powers[0] * powers[1] * powers[2] * powers[3] = 1 * 2 * 4 * 8 = 64 。 每个答案对 109 + 7 得到的结果都相同,所以返回 [2,4,64] 。示例 2:
输入:n = 2, queries = [[0,0]] 输出:[2] 解释: 对于 n = 2, powers = [2] 。 唯一一个查询的答案是 powers[0] = 2 。答案对 109 + 7 取余后结果相同,所以返回 [2] 。提示:
1 <= n <= 109
1 <= queries.length <= 105
0 <= starti <= endi < powers.length
实现原理与步骤
1.bit运算查找所有2的幂集合
2.定义sums[i]数组为前i-1的乘积
3.初始化sums[0]为1,避免后续除法中出现除以0的异常问题。
4.计算前缀乘积
5.查询区间乘积
实现代码
class Solution {
private static final int MOD=1000000007;
public int[] productQueries(int n, int[][] queries) {
List<Integer> powList=decompose(n);
double[] sums=new double[powList.size()+1];
sums[0]=1;
for(int i=0;i<powList.size();i++){
sums[i+1]=sums[i]*powList.get(i);
}
int[] res=new int[queries.length];
for(int i=0;i<queries.length;i++){
int left=queries[i][0];
int right=queries[i][1];
if(left==right){
res[i]=powList.get(left);
}else{
res[i]=(int)(sums[right+1]/sums[left]%MOD);
}
}
return res;
}
public List<Integer> decompose(int number) {
List<Integer> result = new ArrayList<>();
int power = 0;
while (number > 0) {
if ((number & 1) == 1) {
result.add(1<<power);
}
number >>= 1; // 将数字右移一位,相当于除以 2
power++;
}
return result;
}
}