1. 程式人生 > >和為K的子陣列-leetCode560

和為K的子陣列-leetCode560

題目描述:

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

示例 1 :
輸入: nums = [1,1,1], k = 2
輸出: 2 , [1,1] 與 [1,1] 為兩種不同的情況。

說明 :
 	陣列的長度為 [1, 20,000]。
 	陣列中元素的範圍是 [-1000, 1000] ,且整數 <strong>k </strong>的範圍是 [-1e7, 1e7]。

1、 第一種方法是找到所有的連續子陣列然後計算陣列和,和為k則加一。找到所有的連續子陣列的時間複雜度是 O
( n 2 ) O(n^2)
,計算他們的和為 O ( n
) O(n)
,所以總時間複雜度為 O ( n 3 ) O(n^3)
。在本題裡,陣列長度n在[1, 20,000]範圍內,所以這種方法會超時。

2、 第二種方法與第一種方法前一部分類似,找到所有的連續子陣列,但是它計算陣列和時,使用一種累加的方法,將第二部分的時間複雜度降為了 O ( 1 ) O(1) ,總時間複雜度為 O ( n 2 ) O(n^2) 。在本例中不會超時,我一開始就是使用的這種方法,下面是程式碼:
class Solution {
    public int subarraySum(int[] nums, int k) {
        int count=0;
        int sum[]=new int [nums.length];
        int s=0;
        for(int i=0;i<nums.length;i++){
            sum[i]=nums[i]+s;
            s=sum[i];
            if(sum[i]==k) ++count;
        }
        for(int i=1;i<nums.length;i++){
            for(int j=i;j<nums.length;j++){
                sum[j]-=nums[i-1];
                if(sum[j]==k) ++count;
            }
        }
        return count;
    }
}

方法2的其中一個缺點是使用了 O ( n ) O(n) 的額外空間,因此方法3在方法2的基礎上進行改進,空間複雜度僅為 O ( 1 ) O(1)


3、第三種方法是在找連續子陣列的時候,計算累加和,在新增加一個數字時,只需在累加和上增加該數字,因此時間複雜度時 O ( n 2 ) O(n^2) ,空間複雜度為 O ( 1 ) O(1)

4、第四種方法是使用HashMap(當時沒想到,看的推薦解法,也貼上來,待翻譯。。。主要看圖)。

The idea behind this approach is as follows: If the cumulative sum(repreesnted by sum[i] for sum upto i^th index) upto two indices is the same, the sum of the elements lying in between those indices is zero. Extending the same thought further, if the cumulative sum upto two indices, say i and j is at a difference of k i.e. if sum[i] - sum[j] = k, the sum of elements lying between indices i and j is k.

Based on these thoughts, we make use of a hashmap mapmap which is used to store the cumulative sum upto all the indices possible along with the number of times the same sum occurs. We store the data in the form: (sum_i, no. of occurences of sum_i). We traverse over the array numsnums and keep on finding the cumulative sum. Every time we encounter a new sum, we make a new entry in the hashmap corresponding to that sum. If the same sum occurs again, we increment the count corresponding to that sum in the hashmap. Further, for every sum encountered, we also determine the number of times the sum sum-k has occured already, since it will determine the number of times a subarray with sum k has occured upto the current index. We increment the countcount by the same amount.

After the complete array has been traversed, the countcount gives the required result.

The animation below depicts the process.

public class Solution {
    public int subarraySum(int[] nums, int k) {
        int count = 0, sum = 0;
        HashMap < Integer, Integer > map = new HashMap < > ();
        map.put(0, 1);
        for (int i = 0; i < nums.length; i++) {
            sum += nums[i];
            if (map.containsKey(sum - k))
                count += map.get(sum - k);
            map.put(sum, map.getOrDefault(sum, 0) + 1);
        }
        return count;
    }
}