leetcode前缀和(2438. 二的幂数组中查询范围内的乘积)

前言

经过前期的基础训练以及部分实战练习,粗略掌握了各种题型的解题思路。现阶段开始专项练习。

描述

给你一个正整数 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;
    }
}

1.QA:

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值