leetcode - 560. 和爲K的子數組

原題地址:https://leetcode-cn.com/problems/subarray-sum-equals-k/

題目:

給定一個整數數組和一個整數 k,你需要找到該數組中和爲 k 的連續的子數組的個數。

示例 1 :

輸入:nums = [1,1,1], k = 2
輸出: 2 , [1,1] 與 [1,1] 爲兩種不同的情況。
說明 :

數組的長度爲 [1, 20,000]。
數組中元素的範圍是 [-1000, 1000] ,且整數 k 的範圍是 [-1e7, 1e7]。

題解:

方法一:

題目要求對連續子數組求和,然後計算區間爲[i, j]的和是否等於k。 可以O(n^2)的遍歷所有區間做判斷。那麼如何快速的求所有的區間和呢?答案是預先計算前n項和:sum[i] = sum[i-1] + nums[i]; 每次計算區間的時候O(1)的計算區間[j, i]和:sum[i] - sum[j-1] 。時間複雜度是O(n^2),空間複雜度是O(n)

代碼:

int subarraySum(int* nums, int numsSize, int k){
    int sum[numsSize + 7];
    for(int i = 1;i <= numsSize; i++) {
        sum[i] = sum[i-1] + nums[i-1];
    }
    int num = 0;
    for(int i = 1 ; i<= numsSize ;i++) {
        for(int j = 1; j<= i;j++) {
            if(sum[i] - sum[j-1] == k) num ++ ;
        }
    }
    return num;
}

 方法二:

考慮如何降低時間複雜度,一般向這種兩次遍歷的可以向HashMap方向考慮,以空間換時間。方法一中有公式sum[i] - sum[j-1] == k表示符合條件的情況,那麼將公式變化一下:sum[j-1] = sum[i] - k, j = [0, i]。如果將sum[j -1 ], j = [0, i]的count值做一個map的話就可以線性的計算以i 結尾的區間和中符合條件的了。

現在設sum爲前n項和的變量,當計算i位置的時候,0~i的前n項和都已經做了計算了並保存到map中,計算到i位置的時候,此時map中存的正好是0~i的前i項和的count值。這樣時間複雜度是O(n), 空間複雜度O(2n)

class Solution {
    public int subarraySum(int[] nums, int k) {
        int count = 0, sum = 0;
        HashMap<Integer, Integer> mp = new HashMap<Integer, Integer>();
        for(int i = 0; i< nums.length;i++) {
            sum += nums[i];
            // 計算到i的時候,mp中保存的正好 0 ~ i的和的count值
            if(mp.containsKey(sum - k)) count += mp.get(sum -k);
            mp.put(sum, mp.getOrDefault(sum, 0) + 1); //將sum[i]保存更新到map中
        }

        return count;
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章