Given a binary array, find the maximum length of a contiguous subarray with equal number of 0 and 1.
Example 1:
Input: [0,1] Output: 2 Explanation: [0, 1] is the longest contiguous subarray with equal number of 0 and 1.
Example 2:
Input: [0,1,0] Output: 2 Explanation: [0, 1] (or [1, 0]) is a longest contiguous subarray with equal number of 0 and 1.
Note: The length of the given binary array will not exceed 50,000.
題目大意:給定一個二值數組,返回含有相同個數的0和1的最長連續子數組的長度。
方法一:暴力法(超時)
C++代碼
我們考慮所有的連續子數組,判斷0和1個數是否相同,如果相同,則與當前已找到的符合條件的連續子數組的長度進行比較。
1 int findMaxLength(vector<int>& nums) { 2 int sum = 0; 3 int maxsize = 0; 4 for (int i = 0; i < nums.size(); ++i) { 5 sum = 0; 6 for (int j = i; j < nums.size(); ++j) { 7 //計算[i,j]的和,[i, j]的和=[i,j-1]的和+j,所以可以利用前面得到的結果 8 (nums[j] == 1) ? (sum += 1) : (sum -= 1); 9 if (sum == 0 && (maxsize < j - i + 1)) { 10 maxsize = j - i + 1; 11 } 12 } 13 } 14 return maxsize; 15 }
在這裏,我們討論索引[i,j]中1和0的個數是否相等時,避免直接統計1和0的個數,而是利用累加和,是1則加1,0則減1,累加和爲0則代表1和0個數相同。
時間複雜度:$O(n^2)$
空間複雜度:$O(1)$
方法二:哈希表
假設S[i]表示數組索引爲0到i的子數組各元素之和(遇到1則加1,遇到0則減1),如果S[i]=0,那麼[0,i]組成的子數組是符合條件的;
假如S[i] !=0 且 S[i] = m,然而存在最小的$j \in [0,i)$使得S[j] = m,那麼[j+1, i]是符合條件的連續子數組。因爲S[i]=S[j],我們要根據累加和m,得到索引j,所以需要建立累加和映射到索引的哈希表。
累加和的取值範圍爲[-n, n](n爲數組的長度,-n時表示數組全爲-1, n時表示數組全爲1),所以開闢一個2n+1的數組。
1 int findMaxLength(vector<int>& nums) { 2 int len = nums.size(); 3 vector<int> index(2 * len + 1, -2); //初始化爲-2表示這些累加和尚未出現 4 index[len] = -1; //一開始累加和爲0,索引爲-1 5 int maxlen = 0, sum = 0; 6 for (int i = 0; i < nums.size(); ++i) { 7 sum += (nums[i] == 0) ? -1 : 1; 8 if (index[sum + len] >= -1) { //如果當前累加和已經出現過,則比較大小並更新maxlen,這裏就不用更新累加和對應的索引 9 maxlen = max(maxlen, i - index[sum + len]); 10 } else { //否則記錄累加和對應的索引 11 index[sum + len] = i; 12 } 13 } 14 return maxlen; 15 }
需要注意的是,累加和爲m可能對應多個索引,因爲要找最長的連續子數組,所以我們只能保存最小的索引。
時間複雜度:$O(n)$
空間複雜度:$O(n)$
或者利用STL map數據結構:
1 int findMaxLength(vector<int>& nums) { 2 int len = nums.size(); 3 unordered_map<int, int> hM; 4 int maxlen = 0, sum = 0; 5 for (int i = 0; i < nums.size(); ++i) { 6 sum += (nums[i] == 0) ? -1 : 1; 7 if (sum == 0) 8 maxlen = i + 1; 9 if (hM.find(sum + len) != hM.end()) { 10 maxlen = max(maxlen, i - hM[sum + len]); 11 } else { 12 hM[sum + len] = i; 13 } 14 } 15 return maxlen; 16 }