1. 程式人生 > >[leetcode] Range Sum Query - Immutable

[leetcode] Range Sum Query - Immutable

cti lin [] arr change interview nts 總結 fin

Given an integer array nums, find the sum of the elements between indices i and j (ij), inclusive.

Example:

Given nums = [-2, 0, 3, -5, 2, -1]

sumRange(0, 2) -> 1
sumRange(2, 5) -> -1
sumRange(0, 5) -> -3

Note:

  1. You may assume that the array does not change.
  2. There are many calls to sumRange
    function.

分析:翻譯一下,給定一個數組nums,要求找(i,j)位置中間的和,也就是nums[i]+...+nums[j]。最差的方法當然是一個一個求和,但是因為這個題目很巧妙,他在一個題目中設計了很多用例,也就是說很多計算結果會被重復用到,因此需要不能單純的來一個用例就求和一次,要保存中間結果。很容易就想到用動態規劃來做數組的求和,維護一個dp數組,其中dp[i]表示從0到第i位置的和,狀態轉移方程也很容易就得到了:dp[i] = dp[i-1]+nums[i],那麽求(i,j)的和就是dp[j]-dp[i-1]就好了。代碼如下:
 1 class NumArray {
2 int[] dp; 3 public NumArray(int[] nums) { 4 if ( nums == null || nums.length == 0 ) return ; 5 dp = new int[nums.length]; 6 dp[0]=nums[0]; 7 for ( int i = 1 ; i < nums.length ; i ++ ){ 8 dp[i] = dp[i-1]+nums[i]; 9 } 10 } 11 12
public int sumRange(int i, int j) { 13 return i==0?dp[j]:dp[j]-dp[i-1]; 14 } 15 }

這裏要註意第4行。運行時間125ms,擊敗96.34%。

感覺還是有優化的空間的,因為這種方法考慮太多的特殊情況,能不能想辦法將特殊情況也總結進去。看了一下solution,神奇的發現用一個長度為nums.length+1的數組就可以避免兩種特殊情況的討論了。代碼如下:

 1 private int[] sum;
 2 
 3 public NumArray(int[] nums) {
 4     sum = new int[nums.length + 1];
 5     for (int i = 0; i < nums.length; i++) {
 6         sum[i + 1] = sum[i] + nums[i];
 7     }
 8 }
 9 
10 public int sumRange(int i, int j) {
11     return sum[j + 1] - sum[i];
12 }

設計很巧妙,可以學習。

[leetcode] Range Sum Query - Immutable