壹 ❀ 引

本题来自LeetCode303. 区域和检索 - 数组不可变,属于一道简单题,不过题目期望的做法我也是看了题解才懂得,这里大致做个记录,题目描述如下:

给定一个整数数组 nums,求出数组从索引 i 到 j(i ≤ j)范围内元素的总和,包含 i、j 两点。

实现 NumArray 类:

NumArray(int[] nums) 使用数组 nums 初始化对象

int sumRange(int i, int j) 返回数组 nums 从索引 i 到 j(i ≤ j)范围内元素的总和,包含 i、j 两点(也就是 sum(nums[i], nums[i + 1], ... , nums[j]))

示例:

输入:

["NumArray", "sumRange", "sumRange", "sumRange"]
[[[-2, 0, 3, -5, 2, -1]], [0, 2], [2, 5], [0, 5]]

输出:

[null, 1, -1, -3]

解释:

NumArray numArray = new NumArray([-2, 0, 3, -5, 2, -1]);
numArray.sumRange(0, 2); // return 1 ((-2) + 0 + 3)
numArray.sumRange(2, 5); // return -1 (3 + (-5) + 2 + (-1))
numArray.sumRange(0, 5); // return -3 ((-2) + 0 + 3 + (-5) + 2 + (-1))

提示:

0 <= nums.length <= 104

-105 <= nums[i] <= 105

0 <= i <= j < nums.length

最多调用 104 次 sumRange 方法

贰 ❀ 简单分析与暴力题解

题目其实不难理解,我们需要定义一个类NumArray,它接受一个数组nums作为初始化对象,然后调用此类的sumRange方法并传递两个参数i与j,并求出nums中索引i到索引j(i<=j且包含i与j)之间所有元素的和。

不用看官方给的例子,它给的输入看着有点莫名其妙,说直接点就是,假设我们有个数组[1,2,3,4]作为初始化参数,那么调用sumRange(1,3),得到的就是9,因为索引1是2,到索引3是4,中间还有个3,因此和为2+3+4

站在JS角度,这里我直接使用构造函数模拟这个类,因为暴力解法非常简单,这里直接贴代码:

/**
* @param {number[]} nums
*/
var NumArray = function(nums) {
this.nums = nums;
}; /**
* @param {number} i
* @param {number} j
* @return {number}
*/
NumArray.prototype.sumRange = function(i, j) {
let sum = 0;
while(i<=j){
sum+=this.nums[i++]
};
return sum;
};

在上述代码中,NumArray接受一个函数作为参数,之后调用sumRange时,我们也只需要通过遍历,将从i到j的所有数字累加,并最终返回结果即可。

叁 ❀ 前缀和

但事实上,如果你没了解过前缀和的概念,你可能完全不会想到此题的真正考点是希望你用前缀和来解决此问题。

站在暴力解法的角度,我们每调用一次sumRange其实都得从头开始把范围内的数字都重新加一半,这种行为是不具备缓存性质的。那么有没有什么办法,能够让我们在调用sumRange时不用做重复的工作,而是直接得到结果呢,这里就得介绍前缀和了。

也不卖关子,我们以一个数组[1,2,3,4,5]为例,所谓前缀和其实就是第i项保存了包含i以及i之前所有元素的和。

我们假设有个专门的数组用于存放前缀和,它的结果应该是这样:

元素:  1,2,3,4,5
前缀和:1,3,6,10,15

第一个前缀和为1,这是因为目前只有一个,因此为1。

第二个前缀和为3,这是因为2前面还有一个1,因此为1+2=3

第三个前缀和为6,这是因为1+2+3=6,但是我们之前已经计算过1+2了,因此我们可以用上次的前缀和加上当前元素就好了,简化为3+3

以此类推,假设前缀和的数组为preSum,那么:

preSum[i] = preSum[i-1] + nums[i]

我们期望上面的公式能适用于数组遍历的整个过程,但很明显当索引为0时,此时只有一个元素1,都不存在preSum[i-1],怎么办呢?聪明的前辈们想到了一个机智的做法,nums不是长度为5吗,那我的preSum初始化时长度就在nums长度基础上加个1也就是6,并将preSum[0]直接设置为0,也就是:

let preSum = new Array(nums.length);
preSum[0] = 0;

直接让pre多出一个,并将其设置为0,方便后续每一次的前缀和计算,简直妙哉。因此我们可以在第一次遍历数组时,就得到对应的前缀和数组,上代码:

var NumArray = function (nums) {
// 我需要一个length+1的数组,用于保存前缀和
const preSum = new Array(nums.length + 1);
// 为了让前缀和的公式适用于数组每一位计算,所以将0位的值设置为0
preSum[0] = 0;
// 虽然公式是pre[i] = pre[i-1] + nums[i],但是索引是从0开始的,因此preSum的第一位应该是i+1
for (let i = 0; i < nums.length; i++) {
preSum[i + 1] = preSum[i] + nums[i];
}
this.preSum = preSum;
};

OK,那么到这里我们得到了一个前缀和数组,但题目的目的是调用sumRange(i,j)时能得到次区间的和,怎么办呢?

还是举个简单的例子,以数组[1,2,3,4,5]为例,求假设i为1,j为3,求i-j区间的和。

首先0-3的和为1+2+3+4,而1-3的和为2+3+4,因此可以得知,1-3的和可以是0-3的和减去一个1,也就是减去一个preSum[i-1]

但由于我们在声明preSum时长度加了个1,因此从要跟nums的下标对应的话,我们在计算时,公式应该为:

sumRange(i, j) = preSum[j + 1] - preSum[i]

还是上面的数组例子,假设要求1-3的区间和,很明显应该是10-1=9,说到底就是初始值0的问题,要让j加一位,这样计算才是正确的。

元素:  1,2,3,4,5
前缀和:0,1,3,6,10,15

综合上述代码,可以以前缀和的思路得到最终代码:

var NumArray = function (nums) {
// 我需要一个length+1的数组,用于保存前缀和
const preSum = new Array(nums.length + 1);
// 为了让前缀和的公式适用于数组每一位计算,所以将0位的值设置为0
preSum[0] = 0;
// 虽然公式是pre[i] = pre[i-1] + nums[i],但是索引是从0开始的,因此preSum的第一位应该是i+1
for (let i = 0; i < nums.length; i++) {
preSum[i + 1] = preSum[i] + nums[i];
}
this.preSum = preSum;
}; NumArray.prototype.sumRange = function (i, j) {
return this.preSum[j + 1] - this.preSum[i];
};

这样每次查询区间和时,我们都能利用之前遍历缓存的前缀和高效得到最终结果,大功告成,本文结束。

JS LeetCode 303. 区域和检索 - 数组不可变,一维数组的前缀和的更多相关文章

  1. Java实现 LeetCode 303 区域和检索 - 数组不可变

    303. 区域和检索 - 数组不可变 给定一个整数数组 nums,求出数组从索引 i 到 j (i ≤ j) 范围内元素的总和,包含 i, j 两点. 示例: 给定 nums = [-2, 0, 3, ...

  2. [Leetcode]303.区域和检索&&304.二维区域和检索

    题目 1.区域和检索: 简单题,前缀和方法 乍一看就觉得应该用前缀和来做,一个数组多次查询. 实现方法: 新建一个private数组prefix_sum[i],用来存储nums前i个数组的和, 需要找 ...

  3. LeetCode:区域和检索【303】

    LeetCode:区域和检索[303] 题目描述 给定一个整数数组  nums,求出数组从索引 i 到 j  (i ≤ j) 范围内元素的总和,包含 i,  j 两点. 示例: 给定 nums = [ ...

  4. Leetcode 304.二维区域和检索-矩阵不可变

    二维区域和检索 - 矩阵不可变 给定一个二维矩阵,计算其子矩形范围内元素的总和,该子矩阵的左上角为 (row1, col1) ,右下角为 (row2, col2). 上图子矩阵左上角 (row1, c ...

  5. Java实现 LeetCode 304 二维区域和检索 - 矩阵不可变

    304. 二维区域和检索 - 矩阵不可变 给定一个二维矩阵,计算其子矩形范围内元素的总和,该子矩阵的左上角为 (row1, col1) ,右下角为 (row2, col2). Range Sum Qu ...

  6. [Swift]多维数组的表示和存储:N维数组映射到一维数组(一一对应)!

    数组:有序的元素序列. 若将有限个类型相同的变量的集合命名,那么这个名称为数组名.组成数组的各个变量称为数组的分量,也称为数组的元素,有时也称为下标变量.用于区分数组的各个元素的数字编号称为下标.数组 ...

  7. PHP开发小技巧③—实现多维数组转化为一维数组

    在平常的项目开发中我们多会用到让多维数组转化为一维数组的情况,但是很多Programmer不会将其进行转化,也有些没有想到很好的算法然后经过乱起八糟的运算方式将其勉强转化好,但是所写的程序代码冗余非常 ...

  8. 二维数组转化为一维数组 contact 与apply 的结合

    将多维数组(尤其是二维数组)转化为一维数组是业务开发中的常用逻辑,除了使用朴素的循环转换以外,我们还可以利用Javascript的语言特性实现更为简洁优雅的转换.本文将从朴素的循环转换开始,逐一介绍三 ...

  9. Java实现 LeetCode 307 区域和检索 - 数组可修改

    307. 区域和检索 - 数组可修改 给定一个整数数组 nums,求出数组从索引 i 到 j (i ≤ j) 范围内元素的总和,包含 i, j 两点. update(i, val) 函数可以通过将下标 ...

  10. [C++]指针和指向数组的指针[一维数组与指针]

     1.一维数组与指针      形如:int型 数组 a[10]                1)&a[0]  地址常量;地址类型:int *型   ; 存储数组a的首地址          ...

随机推荐

  1. go 接口学习笔记

    这里是对接口在汇编层面上转换和实现的小结,详细了解可参考 Go 语言接口的原理 1. 类型转换:结构体到接口 1.1 结构体方法实现接口 package main type Duck interfac ...

  2. 《DREEAM Guiding Attention with Evidence for Improving Document-Level Relation Extraction》阅读笔记

    代码   原文地址   预备知识: 1.什么是K-L散度(Kullback-Leibler Divergence)? K-L散度,是一种量化两种概率分布P和Q之间差异的方式,又叫相对熵.在概率学和统计 ...

  3. Java 使用二分查找快速定位元素位置

    转载请注明出处: 快速定位 一个有序数列中 某一个元素的位置: 共有三种思路: 第一种:使用 for 循环,匹配元素值 与循环变量的值是否相等,相等则循环变量时的 i 则为元素位置 第二种:使用 二分 ...

  4. 电子科技大学--ARM实验Keil uvison5 安装以及S3C2440A芯片包下载

    1.简介 本教程主要服务于电子科技大学软工嵌入式新生,节省一些查找资料的时间 2.过程 请按如下顺序安装: 1,安装mdk_514.exe (主体文件) 2,安装Keil.STM32F1xx_DFP. ...

  5. Oracle数据库统计信息_执行计划_sharedpool等的知识梳理

    Oracle数据库统计信息_执行计划_sharedpool等的知识梳理 背景 最近有项目出现了年底业务量增加时卡顿的情况. 同事多次发现执行SQL缓慢. 但是重新执行统计信息更新后问题就优化的现象. ...

  6. [转帖]Docker-Compose 自动创建的网桥与局域网冲突解决方案

    https://zhuanlan.zhihu.com/p/379305319 Docker-Compose 自动创建的网桥与局域网冲突解决方案 当我使用docker-compose的方式部署内网的ha ...

  7. [转帖]tidb集群部署

    http://blog.itpub.net/29785807/viewspace-2789852/ 一.安装规划 1 2 3 4 5 6 使用15台服务器 5台tidb服务器:每台3个tidb实例+1 ...

  8. [转帖]Influxdb 2.x 快速入门

    Influxdb 2.x 快速入门 https://www.jianshu.com/p/268fca65f10e Influxdb是由Golang 构建的时序数据库,由于由Go语言构建使得其跨平台部署 ...

  9. [转帖]nginx的luajit安装luarocks并安装luafilesystem

    nginx的luajit安装luarocks并安装luafilesystem by admin on 2015-07-11 08:05:23 in , 69次 标题有点绕口.我尽量把关键词都贴进去.之 ...

  10. memtester 以及 mlc 简单学习

    memtester 以及 mlc 简单学习 下载 memtester https://pyropus.ca./software/memtester/ 下载好后直接进行 make 和make insta ...