Fraction to Recurring Decimal|leetcode題解

這個題目由於有很多的特殊狀況,所以錯誤提交了很多次。

下面是AC代碼,耗時4ms

string fractionToDecimal(int numerator, int denominator) {
      //首先對0進行判斷,以防對最終符號的異或運算結果有干擾    
       if(0==numerator)return "0";
        if(0==denominator)return "";
      //使用異或的方式,判斷兩個數相除的符號,非常好用
       bool sign=(numerator<0)^(denominator<0)?true:false;
        //防止溢出,使用long long
        long long lnumerator=llabs(numerator),ldenominator=llabs(denominator);
        long long integer=lnumerator/ldenominator;
    
        stringstream ss; 
        ss<<integer;
        string left=ss.str();
        left=(sign?"-":"")+left;
        ss.str("");ss.clear();
        if(0==lnumerator%ldenominator)return left; 
        lnumerator%=ldenominator;
       
        map<long long,int>loopPos;    
        string right="";
        bool loop=false;
        int index=0;
        int nZero=0;
        while(lnumerator){
            int i=1;
            while((long long)lnumerator*pow(10,i)<ldenominator)i++;
            long long t=lnumerator*pow(10,i);
            if(loopPos.count(t)){
                loop=true;
                index=loopPos[t];
                nZero=i-1;
                break;
            }
            index+=i;
            loopPos.insert(pair<long long,int>(t,index));
            lnumerator=t%ldenominator;
            long long quotient=t/ldenominator;
            for(int j=1;j<=i-1;j++)ss<<0;
            ss<<quotient;
        }   
        right=loop?ss.str().substr(0,index-1-nZero)+"("+ss.str().substr(index-1-nZero)+")":ss.str();
    
        return left+"."+right;
    }

此問題的基本思路,是確定循環小數循環開始和結束的地方,因此要使用散列表記錄曾經出現的被除數,如果重複出現,則認爲是循環小數。

循環小數結束的地方就是此時商所在的下標的前一位置。

但是循環小數開始的地方,並非是循環小數商首次出現的位置,因爲這個商之前可能出現多個前導0,個數用nZero表示。

另外,此題運算過程中,不要使用int,我的編譯器由於int和long所佔位數相同,因此,爲了避免越界,只能使用long long類型。

如果使用int類型,則可能出現INT_MIN的越界,並且此時abs(INT_MIN)依然是INT_MIN,無法在正數域進行計算。

另外,如果不打算在正數域進行計算,則餘數的處理非常麻煩,因爲在c++中,取餘運算得到的餘數的符號和被除數符號一致,

並且有可能和其他程序的規則不同,因此需要對被除數的符號進行判斷,這樣寫較爲麻煩,建議轉到正數域運算。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章