算法-和爲K的子數組
1、和爲K的子數組
給定一個整數數組和一個整數 k,你需要找到該數組中和爲 k 的連續的子數組的個數。
示例 1 :
輸入:nums = [1,1,1], k = 2
輸出: 2 , [1,1] 與 [1,1] 爲兩種不同的情況。
說明 :
數組的長度爲 [1, 20,000]。
數組中元素的範圍是 [-1000, 1000] ,且整數 k 的範圍是 [-1e7, 1e7]。
這個題是字節面試題,也是Leetcode上一道medium級別的題,題目的意圖也比較明顯,就是找和爲K的連續序列個數。但本題中,數字有可能是亂序的,不能再像劍指offer上那樣用數學法做了。
當然,本題存在暴力解法,時間複雜度爲O(N)。主要思想是聲明兩個指針,一個指向連續序列起始位置,另一個指向連續序列的結尾處,我們利用兩層遍歷,就可以解決這個問題了。方法比較簡單,但時間複雜度爲O(N^2),雖然也能通過測試用例,但要幾百毫秒,換成python這樣的語言一定會超時。
public int subarraySum(int[] nums, int k) {
int slow=0,quick=0;
int tempK=k;
int count=0;
while(slow<nums.length){
if(quick==nums.length){
tempK=k;
quick=++slow;
}else if(tempK-nums[quick]==0){
count++;
tempK-=nums[quick++];
}else{
tempK-=nums[quick++];
}
}
return count;
}
我們可以用哈希表實現另一種解法,還記得leetcode的第一題嗎?two sum問題,存在着一種使用HashMap實現的O(N)解法,本題目思想和它是一致的。
我們用hashmap來保存同一個sum出現的次數,一旦當前sum等於目標和,那麼當前符合條件的數列數量+1,如果包含sum-k,那麼和爲sum-k的m個子序列與當前元素都可以組成連續序列,所以,當前連續子序列個數要加上m。最後,我們要記錄每個和sum的出現次數。
public int subarraySum(int[] nums, int k) {
int sum=0,count=0;
Map<Integer,Integer> map=new HashMap<>();
for (int i=0;i<nums.length;i++){
sum+=nums[i];
if(sum==k){
count++;
}
if(map.containsKey(sum-k)){
count+=map.get(sum-k);
}
if(!map.containsKey(sum)){
map.put(sum,1);
}else {
map.put(sum,map.get(sum)+1);
}
}
return count;
}
代碼寫的比較清晰,不過多解讀了。