題目:
給定一個整數數組和一個整數 **k,**你需要找到該數組中和爲 k 的連續的子數組的個數。
示例1:
輸入:nums = [1,1,1], k = 2
輸出: 2 , [1,1] 與 [1,1] 爲兩種不同的情況。
說明:
數組的長度爲 [1, 20,000]。
數組中元素的範圍是 [-1000, 1000] ,且整數 k 的範圍是 [-1e7, 1e7]。
題目與之前兩數之和、連續子數組和之類的題目比較像,因爲這裏考察的是連續數組,就聯想到可以分別對數組進行遍歷累加,下標i對應的值記錄的是前i個數組值的和,然後每個子數組和可由累加後的值相減得到(nums[i]-nums[j],i>j),遍歷時間複雜度是,空間複雜度O(1),效率比較低。
後邊想到一種改進方案,就是求和後升序排序,然後加入判斷條件,從後往前遍歷的話如果差已經小於k說明更前面的子數組均比k小了,可以省略掉。這樣時間複雜度是,但是因爲沒找到java中能排序且返回索引的方法,所以不了了之。
class Solution {
public int subarraySum(int[] nums, int k) {
int ans=0;
for(int i=0;i<nums.length;i++){
nums[i]+=nums[i-1];
}
// Arrays.sort(nums);
for(int i=0;i<nums.length;i++){
for(int j=nums.length-1;j>=i;j--){
if(nums[j]-nums[i]==k) ans++;
// else if(nums[j]-nums[i]<k) break;
}
}
return ans;
}
}
最後想到竟然要查詢爲什麼不用Hashmap呢,遍歷的過程把當前所有遍歷值的和加入Hashmap中,並查詢map中是否含有值n滿足sum+n=k,這樣能快速實現子數組和的查找,時間與空間複雜度均爲O(n)
class Solution {
public int subarraySum(int[] nums, int k) {
int ans=0,sum=0;
HashMap < Integer, Integer > tmp = new HashMap < > ();
tmp.put(0,1);
for(int i=0;i<nums.length;i++){
sum+=nums[i];
if(tmp.containsKey(sum-k))
ans+= tmp.get(sum - k);
if(tmp.containsKey(sum))
tmp.put(sum,tmp.get(sum)+1);
else
tmp.put(sum, 1);
}
return ans;
}
}
看了題解之後比較驚豔的是代碼的寫法,關於hashmap的更新問題的那一句定了我四行的if else,不得不說要學習的東西還是很多
mp.put(pre, mp.getOrDefault(pre, 0) + 1);