题目
1 | class NumArray { |
My way
1. 暴力法
1 | class NumArray { |
结果,时间复杂度极低,仅超过10%的解。
很明显是要先用dp数组存入各个索引i, j对应的值。
2. 2维DP
状态转移方程:
dp[i][j]=dp[i][j−1]+nums[j−1]
1 | class NumArray { |
结果更慢了,仅超过5%的解。。。
应该是哪里思路出了问题...
1 | class NumArray { |
换成原生数组,时间复杂度仅超过7%,仍然很糟糕。。。
假如直接静态数组int dp[INT_MAX][INT_MAX];
,内存会炸掉。。。
官方way
2. 缓存
将计算结果提前存入到 哈希表 中。
PS:而我用的是vector<vector<int>> dp, int **dp
, 感觉没区别,应该是resize()/动态分配内存
那耗费了不少时间。
1 | private Map<Pair<Integer, Integer>, Integer> map = new HashMap<>(); |
3. 缓存
优化空间复杂度从O(n2)=>O(n). sum[k]={∑k−1i=0nums[i],k>00,k==0 优化为: sumrange(i, j)=sum[j+1]−sum[i] java:
1 | private int[] sum; |
C++: use array
1 | class NumArray { |
但这也只超过了 78.45%...
C++: user vector<int>
1 | class NumArray { |
超过了96.23%,代码类似 陈乐乐解2.
但仔细看她代码,你会发现她在C++编码时,有个很不好的习惯,我在这纠正了,就不指出来了。
总结
- 傻了,老想着把计算结果存起来,到时候直接取,居然忘记了
- sumrange(i, j)=sum[j+1]−sum[i]
- 这里也用到了插入了一个虚拟 0 作为 sum 数组中的第一个元素。
- 这个技巧可以避免在 sumrange 函数中进行额外的条件检查,对于base case, corner case等等
- PS:尽管,我其实喜欢加上对于base case, corner case的检查,但却是实现起来有些冗余