题目
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(n^2) = > O(n)\). \[ sum[k] = \begin{cases} & \sum_{i=0}^{k-1} nums[i] & , k > 0 \\ & 0 & , k == 0\\ \end{cases} \] 优化为: \[ 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的检查,但却是实现起来有些冗余