1 題目描述
- 523. 連續的子數組和
給定一個包含非負數的數組和一個目標整數 k,編寫一個函數來判斷該數組是否含有連續的子數組,其大小至少爲 2,總和爲 k 的倍數,即總和爲 n*k,其中 n 也是一個整數。
示例 1:
輸入: [23,2,4,6,7], k = 6
輸出: True
解釋: [2,4] 是一個大小爲 2 的子數組,並且和爲 6。
- 560. 和爲K的子數組
給定一個整數數組和一個整數 k,你需要找到該數組中和爲 k 的連續的子數組的個數。
示例 1 :
輸入:nums = [1,1,1], k = 2
輸出: 2 , [1,1] 與 [1,1] 爲兩種不同的情況。
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/subarray-sum-equals-k
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。
2 解題思路
- 523. 連續的子數組和
方法1:暴力 [Time Limited Exceeded]
暴力方法是很顯然的。我們考慮所有長度大於等於 2 的子數組,我們將子數組遍歷一遍求和,並判斷和是否是給定整數 k 的倍
方法 2:使用累加和 [Accepted]
可以在某種程度上優化暴力算法。如果我們用一個額外的 sum 數組保存數組的累積和,那麼 sum[i] 保存着到第 i 個元素位置的前綴和。
因爲,就如前面所述,我們考慮每一個子數組並求它的和。但是與剛剛不同的是,我們不會遍歷整個子數組來求和,我們只需要使用數組的前綴和。因此,求第 i 個數到第 j 個數,我們只需要求出 sum[j]−sum[i]+nums[i] 。
- 560. 和爲K的子數組
方法一 暴力 [超出時間限制]
最簡單的方法是考慮給定 nums 數組的每個可能的子數組,找到每個子數組的元素總和,並檢查使用給定 k 獲得的總和是否相等。當總和等於 k 時,我們可以遞增用於存儲所需結果的 count。
方法二 使用累計和 [通過]
對於每個考慮的新子數組,我們不是每次都計算元素的總和,而是使用累積和數組 sum。然後,爲了計算位於兩個索引之間的元素之和,我們可以減去對應於兩個索引的累積和以直接獲得總和,而不是迭代子數組以獲得總和。
這個實現是基於累加和數組 sum,sum[i] 用於存儲 nums 的序號 0 到 (i−1) th之間元素的和,所以,爲了確定子數組 nums[i:j] 的元素總和,我們可以直接使用 sum[j+1]−sum[i],並可以通過 sum[j+1]−sum[i] 來得到子數組 nums[i:j] 的和。
三 兩道題目比較
官方題解都是給出了暴力法和累加和兩種解法,暴力法就真的比較暴力,三次嵌套循環解決問題,
對於累加和來說,就是利用一個數組去存儲它的累積和,這樣就可以索引對應相減就可以,而不用每次都迭代獲得總和,大大減少了時間複雜度。
兩道題目的兩種代碼基本都如出一轍,只是臨界條件不同,相似度+++
四解決代碼
- 523. 連續的子數組和
方法1:暴力 [Time Limited Exceeded]
public class Solution {
public boolean checkSubarraySum(int[] nums, int k) {
for (int start = 0; start < nums.length - 1; start++) {
for (int end = start + 1; end < nums.length; end++) {
int sum = 0;
for (int i = start; i <= end; i++)
sum += nums[i];
if (sum == k || (k != 0 && sum % k == 0))
return true;
}
}
return false;
}
}
方法 2:使用累加和 [Accepted]
public class Solution {
public boolean checkSubarraySum(int[] nums, int k) {
int[] sum = new int[nums.length];
sum[0] = nums[0];
for (int i = 1; i < nums.length; i++)
sum[i] = sum[i - 1] + nums[i];
for (int start = 0; start < nums.length - 1; start++) {
for (int end = start + 1; end < nums.length; end++) {
int summ = sum[end] - sum[start] + nums[start];
if (summ == k || (k != 0 && summ % k == 0))
return true;
}
}
return false;
}
}
- 560. 和爲K的子數組
方法一 暴力 [超出時間限制]
public class Solution {
public int subarraySum(int[] nums, int k) {
int count = 0;
for (int start = 0; start < nums.length; start++) {
for (int end = start + 1; end <= nums.length; end++) {
int sum = 0;
for (int i = start; i < end; i++)
sum += nums[i];
if (sum == k)
count++;
}
}
return count;
}
}
方法二 使用累計和 [通過]
public class Solution {
public int subarraySum(int[] nums, int k) {
int count = 0;
int[] sum = new int[nums.length + 1];
sum[0] = 0;
for (int i = 1; i <= nums.length; i++)
sum[i] = sum[i - 1] + nums[i - 1];
for (int start = 0; start < nums.length; start++) {
for (int end = start + 1; end <= nums.length; end++) {
if (sum[end] - sum[start] == k)
count++;
}
}
return count;
}
}