【經典面試題:最長01子串】 有一個僅由0和1組成的01串,找到其中最長的一段子串,使得該子串中0和1的數目相等

題目

有一個僅由0和1組成的01串,找到其中最長的一段子串,使得該子串中0和1的數目相等

解題思路

  • 如果將0看做-1,則我們要找的子串是最長的和爲0的子串。

  • 這種子串求和的問題,一般採用前綴和的方法來解決。

  • 用Sum[i]代表前i個數的和,問題的模型轉換爲,找到i和j,滿足Sum[i] 與Sum[j]相等,且|i-j|最大。

  • 使用Hash表作爲輔助數據結構,Hash表中記錄了獲得某個Sum時最小的i。從左到右遍歷Sum[i],在Hash表中查找是否存在,如果存在,則記錄下Hash[Sum[i]] 和i的距離差,否則Hash[Sum[i]] = i。一次遍歷結束後得到最大的距離差,同時也可以得到具體是哪一段。

代碼實現(C++)

#include<bits/stdc++.h>
#define endl '\n';
#define mst(a,b) memset(a,b,sizeof(a));
using namespace std;
const int maxn=1e5+5;
int a[maxn];
int n,m,t;
int dp[maxn];
int main(){
    string str;
    while(cin>>str){
        int zeroIndex = 0;
        int len = str.length();
        dp[1] = (str[0]-'0') == 1? 1:-1;  //將0轉變成-1
        for(int i=2;i<=len;i++){
            dp[i] = (str[i-1]-'0') == 1? 1:-1; //將0轉變成-1
            dp[i]+=dp[i-1];   //求前綴和
            if(dp[i]==0) zeroIndex=i;  //記錄當前前綴和爲0的下標位置
        }
        int start = 0 ,maxnlen = 0;
        map<int,int> mp;
        for(int i=1;i<=len;i++){
            if(!mp.count(dp[i])){  //記錄首次出現的前綴和的位置
                mp[dp[i]]=i;
            }else{
                start = mp[dp[i]];  //如果有相同的前綴和,求出最長長度
                maxnlen = i-start;
            }
        }
        string ans;
        if(zeroIndex>=maxnlen){  //對於前綴和爲0的情況特殊考慮
            maxnlen = zeroIndex;   //與相同前綴和的長度取最大值
            ans = str.substr(0,maxnlen);
        }
        else
            ans = str.substr(start,maxnlen);
        cout<<ans<<" "<<maxnlen<<endl;
    }
    return 0;
}

如果需要詳細的步驟介紹,可以參考如下博文:

推薦閱讀——SunnyYoona :[經典面試題]最長01子串

學如逆水行舟,不進則退
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章