尋找寫程式碼感覺(十四)之 新增功能的開發
阿新 • • 發佈:2022-02-04
和為 K 的子陣列
問題重述:
給你一個整數陣列 nums
和一個整數 k
,請你統計並返回該陣列中和為 k
的連續子陣列的個數
示例 1:
輸入:nums = [1,1,1], k = 2
輸出:2
示例 2:
輸入:nums = [1,2,3], k = 3
輸出:2
提示:
1 <= nums.length <= 2 * 104
-1000 <= nums[i] <= 1000
-107 <= k <= 107
問題分析:
一般看到陣列中的連續子陣列求和,我們會想到使用字首和
解法:
字首和
解題:
程式碼:
public static int subarraySum(int[] nums, int k) { // 定義一個字首和陣列 int[] preNums = new int[nums.length+1]; // 字首和陣列的第一個值為0 preNums[0] = 0; // 為字首和陣列賦值 for(int i = 1; i < preNums.length;i++){ preNums[i] = preNums[i-1] + nums[i-1]; } int count = 0; for(int left = 0;left < preNums.length;left++){ for(int right = left+1;right < preNums.length;right++){ if(preNums[right] - preNums[left] == k){ count += 1; } } } return count; } public static int subarraySum1(int[] nums,int k){ int count = 0,pre = 0; Map<Integer,Integer> map = new HashMap<Integer,Integer>(); map.put(0, 1); for(int num : nums) { pre += num; if(map.containsKey(pre - k)) { count += map.get(pre-k); } map.put(pre,map.getOrDefault(pre, 0)+1); } return count; }
程式碼解析:
前面一個方法是單純的字首和方法,時間複雜度為O(N),我們定義了一個字首和陣列,其中的每一個數組元素都對應了原來陣列的前n項和,接下來我們遍歷字首和陣列。我們先固定陣列的左邊界,讓左邊不動,然後陣列的右邊節不斷向右擴張,擴張一個,就將當前的值和k進行對比,如果相同,則count+1,不相同則右邊界擴張。如果右邊界到達了陣列的末尾,將左邊界右移一位,右邊界回到左邊界的起始位置,重新開始,知道左邊界遍歷到陣列的末尾,最後得到的count就是和為k的子陣列個數
第二個方法是對字首和方法的優化,使用雜湊表來幫助我們簡化了求子陣列和的過程。我們在遍歷陣列的時候,每一次都記錄陣列的字首和,雜湊表中以字首和為key,字首和出現的次數作為value存放資料。因為pre[j]-pre[i] = k,所以pre[i] = pre[j]-k
總結:
字首和的適用範圍:在陣列中,當我們要求連續陣列的和的時候,我們就要考慮使用字首和。