给定一个整数数组nums,计算第i个元素到第j个元素的和(i≤j),包括nums[i]和nums[j]。示例:constnums=Object.freeze([-2,0,3,-5,2,-1]);sumRange(0,2)->1sumRange(2,5)->-1sumRange(0,5)->-3注意:假设数组的值不会改变(如上面代码中,nums是可读的并且不可写因为Object.freeze)sumRange可能会被多次使用,不同区间的值数组可能很大(比如超过10000个数),注意运行时间解决问题.这个问题看起来很简单是吧?任何人都可以编写一个简单的函数:constImmutable=Sup=>classextendsSup{constructor(...args){super(...args);对象.freeze(this);}}classNumArrayextendsImmutable(Array){sumRange(i,j){让sum=0;for(;i<=j;i++){sum+=this[i];}返回总和;}}在上面的代码中,我们重构了数组。这里我使用了一个小技巧来让数组元素不可变。这个技巧在我之前翻译的《六大ES6技巧》中有提到,很多同学不理解那篇文章中的第六个技巧,我这里就用到了,当然这与我们的主题无关今天正在讨论。所以我们可以使用新的数组对象来计算sumRange:varnums=newNumArray(-2,0,3,-5,2,-1);nums.sumRange(0,2)->1nums。sumRange(2,5)->-1nums.sumRange(0,5)->-3到目前为止,我们好像什么都没改,只是继承了Array类,把sumRange改成一个对象方法,还是非常慢。那我们接下来做什么?前面说了sumRange需要调用很多次,所以我们想尽可能的降低sumRange调用的复杂度对吧?根据前面的方法,我们使用循环从i到j求和。有没有更快的方法?答案是:空间换时间,查表!查表查表不是查水表,因为sumRange需要多次计算,所以我们可以在构造NumArray的时候计算出sumRange要查的值,预先存入表中。二维表?R/C0123450-2-21-4-2-3103-20-123-20-13-5-3-44215-1二维表各可一个值完全映射到i,j。在这种情况下,空间复杂度变为O(n2)。还记得我们前面说的吗,这个数组可能很大,有10000个元素。如果使用这样的映射表,内存就会溢出。实际上,使用二维表是愚蠢的,因为我们很容易找到以下对应关系:sumRange(i,j)===sumRange(0,j)-sumRange(0,i-1);//(i>0)一维表我们只需要对第一个元素对应的NumArray的每个元素求和,将结果保存为一维表,我们可以用O(1)的时间复杂度来计算sumRange(我,j)!以下是优化后的NumArray:constUniqueID=Sup=>classextendsSup{constructor(...args){super(...args);Object.defineProperty(this,"id",{value:Symbol(),writable:false,enumerable:false});}}constImmutable=Sup=>classextendsSup{constructor(...args){super(...args);对象.freeze(this);}}constNumArray=(function(){letsumTable={};returnclassextendsImmutable(UniqueID(Array)){constructor(...args){super(...args);letsum=0;lettable=[0];for(leti=0;i
