LeetCode解法汇总307. 区域和检索 - 数组可修改

目录链接:

力扣编程题-解法汇总_分享+记录-CSDN博客

GitHub同步刷题项目:

https://github.com/September26/java-algorithms

原题链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

描述:

给你一个数组 nums ,请你完成两类查询。

  1. 其中一类查询要求 更新 数组 nums 下标对应的值
  2. 另一类查询要求返回数组 nums 中索引 left 和索引 right 之间( 包含 )的nums元素的 ,其中 left <= right

实现 NumArray 类:

  • NumArray(int[] nums) 用整数数组 nums 初始化对象
  • void update(int index, int val)nums[index] 的值 更新val
  • int sumRange(int left, int right) 返回数组 nums 中索引 left 和索引 right 之间( 包含 )的nums元素的 (即,nums[left] + nums[left + 1], ..., nums[right]

示例 1:

复制代码
输入:
["NumArray", "sumRange", "update", "sumRange"]
[[[1, 3, 5]], [0, 2], [1, 2], [0, 2]]
输出:
[null, 9, null, 8]

解释:
NumArray numArray = new NumArray([1, 3, 5]);
numArray.sumRange(0, 2); // 返回 1 + 3 + 5 = 9
numArray.update(1, 2);   // nums = [1,2,5]
numArray.sumRange(0, 2); // 返回 1 + 2 + 5 = 8

提示:

  • 1 <= nums.length <= 3 * 104
  • -100 <= nums[i] <= 100
  • 0 <= index < nums.length
  • -100 <= val <= 100
  • 0 <= left <= right < nums.length
  • 调用 updatesumRange 方法次数不大于 3 * 104

解题思路:

复制代码
这题数组的长度为310^4,如果时间复杂度是O(n2),则会超时。所以这题一定不能每次都遍历。 
但是我们可以发现一个规律,就是update的时候,影响的范围很小,甚至有可能都对sumRange不产生影响,所以,我们可以把影响范围缩减到最小。
我们可以把nums数组划分为k块,暂且用N1,N2,Nk表示,则left和right会出现2种情况。 
left和right属于同一块:这种情况,直接求left和right的累加值即可。 
left和right不属于同一块:这种情况,求left到其所属块的尾之间的和,right所属的块的头到right之间的和,以及left和right之间的块的和。三者相加,就是最终值。

代码:

复制代码
class NumArray {
        private int[] nums;
        private int[] pieces;
        private int pieceLength;

        public NumArray(int[] nums) {
            this.nums = nums;
            pieceLength = (int) Math.ceil(Math.sqrt(nums.length));
            pieces = new int[nums.length / pieceLength + 1];
            for (int i = 0; i < nums.length; i++) {
                pieces[i / pieceLength] = pieces[i / pieceLength] + nums[i];
            }
        }

        public void update(int index, int val) {
            pieces[index / pieceLength] += (val-nums[index]);
            nums[index] = val;
        }

        public int sumRange(int left, int right) {
            int piece1 = left / pieceLength;
            int piece2 = right / pieceLength;
            int sum1 = 0, sum2 = 0, sum3 = 0;
            if (piece1 == piece2) {
                for (int i = left; i <= right; i++) {
                    sum1 += nums[i];
                }
            } else {
                for (int i = left; i < pieceLength * (piece1+1); i++) {
                    sum1 += nums[i];
                }
                for (int i = pieceLength * piece2; i <= right; i++) {
                    sum3 += nums[i];
                }
                for (int i = piece1 + 1; i < piece2; i++) {
                    sum2 += pieces[i];
                }
            }
            int sum = sum1 + sum2 + sum3;
            return sum;
        }
    }
相关推荐
啊我不会诶10 分钟前
倍增法和ST算法 个人学习笔记&代码
笔记·学习·算法
程序员三藏19 分钟前
如何使用Pytest进行测试?
自动化测试·软件测试·python·测试工具·职场和发展·测试用例·pytest
你的冰西瓜1 小时前
C++ 中最短路算法的详细介绍
c++·算法·图论·最短路
zstar-_1 小时前
【算法笔记】6.LeetCode-Hot100-链表专项
笔记·算法·leetcode
Swift社区1 小时前
Swift 图论实战:DFS 算法解锁 LeetCode 323 连通分量个数
算法·swift·图论
<但凡.1 小时前
数据结构与算法之美:广义表
数据结构·c++·算法
前端极客探险家1 小时前
告别卡顿与慢响应!现代 Web 应用性能优化:从前端渲染到后端算法的全面提速指南
前端·算法·性能优化
程序员Xu2 小时前
【OD机试题解法笔记】连续出牌数量
笔记·算法·深度优先
CoovallyAIHub2 小时前
单目深度估计重大突破:无需标签,精度超越 SOTA!西湖大学团队提出多教师蒸馏新方案
深度学习·算法·计算机视觉
CoovallyAIHub2 小时前
从FCOS3D到PGD:看深度估计如何快速搭建你的3D检测项目
深度学习·算法·计算机视觉