演算法練習Day11 [LeetCode]560. 和為 K 的子陣列
阿新 • • 發佈:2021-02-03
技術標籤:leetcode演算法JAVAleetcode演算法
560. 和為 K 的子陣列
給定一個整數陣列和一個整數 k,你需要找到該陣列中和為 k 的連續的子陣列的個數。
示例 1 :
輸入:nums = [1,1,1], k = 2
輸出: 2 , [1,1] 與 [1,1] 為兩種不同的情況。
說明 :
陣列的長度為 [1, 20,000]。
陣列中元素的範圍是 [-1000, 1000] ,且整數 k 的範圍是 [-1e7, 1e7]。
暴力解法:
class Solution {
public int subarraySum(int[] nums, int k) {
int len = nums.length;
int sum = 0;
int count = 0;
//雙重迴圈
for (int i = 0; i < len; ++i) {
for (int j = i; j < len; ++j) {
sum += nums[j];
//發現符合條件的區間
if (sum == k) {
count++;
}
}
//記得歸零,重新遍歷
sum = 0;
}
return count;
}
}
用字首和解法
class Solution {
public int subarraySum(int[] nums, int k) {
//字首和陣列
int[] presum = new int[nums.length+1];
presum[0]=0;
for (int i = 0; i < nums.length; i++) {
//這裡需要注意,我們的字首和是presum[1]開始填充的
presum[i+1] = nums[i] + presum[i];
}
//統計個數
int count = 0;
for (int i = 0; i < nums.length; ++i) {
for (int j = i; j < nums.length; ++j) {
//注意偏移
//這樣就可以得到nums[i,j]區間內的和
if (presum[j+1] - presum[i] == k) {
count++;
}
}
}
return count;
}
}
雖然用到了字首和陣列,但是對比暴力法並沒有提升效能,時間複雜度仍為O(n^2),空間複雜度O(n)。
字首和 + HashMap方法解
將所有的字首和,與該字首和出現的次數存到 map 裡。
注意:在此我們設定HashMap中第一個鍵值對為{0,1},我們後期更新count的時候要注意以往鍵值對中是否出現與字首和pre[i]−k 相同的 pre[j] ,所以第一位要設定0,後面出現的字首和減去k=0就可計數count=1。
舉例說明:[3,4,7],k=7;
1.設定第一個鍵值對為{0,1};此時count=0;字首和為0;
2.從3開始:字首和=3,設定第二個鍵值對為{3,1};字首和-k=3-7=-4,-4與已有的鍵值對中的字首和不相等。
3.遍歷4:字首和=7,設定第三個鍵值對為{7,1};字首和-k=7-7=0,0與之前的鍵值對中的字首和0相等,count=1;
4.遍歷7:字首和為14,設定第四個鍵值對為{14,1};字首和-k=14-7=7,7與之前鍵值對中的字首和7相等,count=2;
5.所以輸出count=2。
public class Solution {
public int subarraySum(int[] nums, int k) {
int count = 0, pre = 0;
HashMap < Integer, Integer > mp = new HashMap < > ();
mp.put(0, 1);
for (int i = 0; i < nums.length; i++) {
pre += nums[i];
if (mp.containsKey(pre - k)) {
count += mp.get(pre - k);
}
mp.put(pre, mp.getOrDefault(pre, 0) + 1);
//當Map集合中有這個key時,就使用這個key值,如果沒有就使用預設值defaultValue
}
return count;
}
}
複雜度分析
時間複雜度:O(n),其中 n 為陣列的長度。我們遍歷陣列的時間複雜度為 O(n),中間利用雜湊表查詢刪除的複雜度均為O(1),因此總時間複雜度為 O(n)。
空間複雜度:O(n),其中 n 為陣列的長度。雜湊表在最壞情況下可能有 n個不同的鍵值,因此需要 O(n)的空間複雜度。