一、題目解析
1、只包含0、1的二進制數組
2、找到含有相同數量的0和1,并返回其子數組長度
二、算法原理
解法1:暴力枚舉 時間復雜度O(N^2)
解法2:前綴和+哈希表
對于統計子數組中的0和1的數量有點困難,我們可以將其轉化一下
轉化:
1、將所有的0變為-1
2、在數組中,找出最長子數組,使子數組中所有元素的和為0
將問題轉化后,大體思路與560.和為k的子數組差不多,但還有細節問題問題需要處理,建議先去自己嘗試一下,實在不行再來觀看細節問題
細節問題:
1、哈希表中存什么?
在和為k的子數組中,unordered_map<int,int> hash,第一int存的是前綴和,第二個int存的前綴和出現的頻率,而在本題中,所求的是子數組的長度,所以第一個int存的也是前綴和,第二個int存的是下標
2、什么時候存入哈希表?
在判斷條件結束后,就可以丟進哈希表中
3、如果有重復的<sum,i>該怎么處理?
對于前綴和同樣都為sum的兩個結果,j比i要靠左一點,要想長度越長,左邊的長度必然是最短的,所以對于重復的<sum,i>只保留前面或者最左邊的那一對<sum,i>
4、?默認前綴和為0的hash[0],怎么存儲?
為了避免[0,i-1]的所有元素前綴為0的情況遺漏,在560.和為k的子數組中,我們要在[-1,0]中找到前綴和為0的數組,便將hash[0]的值設置為1,但在該題中計算的是長度,所以hash[0]的值設置為-1
5、長度怎么計算?
由于計算的長度不會包括j元素,所以長度為i-j,這里的j是hash表中存的下標
三、代碼示例
解法2:
class Solution {
public:int findMaxLength(vector<int>& nums){//將數組中所有0變為-1for(auto& e : nums){if(e == 0) e = -1;}//找一段和為0的最長子數組int ret = 0,sum = 0;unordered_map<int,int> hash;hash[0] = -1;for(int i = 0;i<nums.size();i++){sum += nums[i];if(hash.count(sum)) ret = max(ret,i-hash[sum]);else hash[sum] = i;}return ret;}
};
?
?
?