最近偶然碰到的一道題,題目本身解法不難,但屬於挺典型的數組問題處理的一種解法。
該題是利用前綴和的技巧判斷子數組合法性的。(另外一些常用於判斷數組合法性的典型方法有雙指針法即尺取,二分枚舉區間等。)
題目:
給定一個二進制數組, 找到含有相同數量的 0 和 1 的最長連續子數組。
示例 1:
輸入: [0,1] 輸出: 2 說明: [0, 1] 是具有相同數量0和1的最長連續子數組。
示例 2:
輸入: [0,1,0] 輸出: 2 說明: [0, 1] (或 [1, 0]) 是具有相同數量0和1的最長連續子數組。
注意: 給定的二進制數組的長度不會超過50000。
題解:
首先對原數組做處理,將所有的0都變為-1;這樣一來 “含有相同數量的 0 和 1 的連續數組” 就等價為 “元素值總和為0的連續數組”。
其后,從頭掃一遍數組,並記錄當前的前綴和的值,將該值和對應的下標存入到一個標記數組或哈希表中。若該前綴和的值已出現過(即標記數組或哈希中已存在),則說明標記中的下標到當前掃描的下標的這段數組的總和值是為0的。
打個例子: [ -1,-1,-1,1,-1,1,-1,1,-1,-1,-1,-1 ] 在掃描完到第四個元素時,前綴和為-2 且未記錄過,則將值-2和下標3記錄起來。當掃描到 [ -1,-1,-1,1,-1,-1,1,1,-1,-1,-1,-1 ] , 此時得到的前綴和為-2,且知道標記中有記錄過-2,則說明此刻下標到之前記錄的下標的這段數組總和為0 [ -1,-1,-1,1,-1,-1,1,1,-1,-1,-1,-1 ] 。
1 class Solution { 2 public int findMaxLength(int[] nums) { 3 int ans = 0,sum = 0; 4 for(int i=0;i<nums.length;i++)if(nums[i]==0)nums[i]=-1; 5 HashMap<Integer,Integer> map = new HashMap(); 6 for(int i=0;i<nums.length;i++) { 7 sum+=nums[i]; 8 if(sum == 0) { if(i >= ans) ans = i+1; } 9 if(map.get(sum) == null) { map.put(sum,i); continue; } 10 int temp = i - map.get(sum); 11 if(temp > ans) ans=temp; 12 } 13 return ans; 14 } 15 }
