找符合條件的整數

     任意給定一個正整數N,求一個最小的正整數M(M>1),使得N*M的十進制表示形式裏只含有1和0。

     第一想法:從小到大枚舉M的取值,然後再計算N*M,最後判斷它們的乘積是否只含有1和0。該方法時間複雜度太高。

     第二想法:因爲問題要求N*M的十進制表示形式裏只含有1和0,嘗試去搜索N*M,需要搜索的空間要小很多。

     終極思路:(避免多於的除法驗證餘數)如1%3=1;10%3=1;101%3=2那麼我們可以知道110%3=2。即1和10加上相同的數,他們的餘數都相同,所以我們只需要考慮1,11,101,1001而不用考慮10,110,1010。對於modN同餘的數,只需要記錄最小的一個。形式化論述:假設已經遍歷了X的十進制表示有K位時的所有情況,而且也搜索了X=10^K的情況,設10K%N=a。現在要搜索X有K+1位的情況,即X=10K+Y,(0<Y<10K)。把Y按照其對N的餘數分類,我們搜索的空間將被分成N-1個子空間。對於每個子空間,其實只需要判斷其中最小的元素加上10K是否被N整除即可,而沒有必要判斷這個子空間裏所有元素加上10K是否能被N整除。

     僞代碼描述:BigInt[i]表示模N等於i的十進制表示形式裏只含1和0的最小整數。由於BigInt[i]可能很大,又因爲它只有0和1,所以只需要記下1的位置即可。如1001記爲(0,3)=10^0+10^3。即BigInt的每個元素是一個變長數組,對於模N等於i的最小X,BigInt的每個元素將存儲最小X在十進制中表示1的位置。我們的目標就是求BigInt[0]。

public static String find01Int(int N){

                   intNoUpdate = 0;

                   LinkedList<Integer>[]kt = new LinkedList[N];

                   for(int i = 0;i<N;i++){

                            kt[i] = new LinkedList<Integer>();

                   }

                   kt[1].push(0);

                   //i=1從十位開始,顯然,個位1已經放入kt[1]

                   for(int i = 1,j=10%N;;i++,j=(j*10)%N){

                            boolean flag = false;

                            if(kt[j].size()==0){

                                     kt[j].clear();

                                     kt[j].push(i);

                            }

                            for(int k = 1;k<N;k++){

                                     //用於判斷含有餘數的項並且是低位(<i),並加上高位後產生的餘數是新的

                                     //餘數,則把得出該餘數的最小值記錄下來

                                     if((kt[k].size()>0)&&

                                                        (i>kt[k].peek())&&

                                                        (kt[(k+j)%N].size()==0)){

                                               flag= true;

                                               //這步賦值很重要,不能漏,因爲該最小值前面幾項在kt[k]

                                               for(int p = 0;p<kt[k].size();p++){

                                                        kt[(k+j)%N].add(kt[k].get(p));

                                               }

                                               kt[(k+j)%N].push(i);

                                     }

                            }

                            if(flag==false)

                                     NoUpdate++;

                            else

                                     NoUpdate =0;

//如果經過一個循環都沒能對BigInt進行更新,就是無解,跳出,或者BigInt[0]已經找到也跳出

                            if(NoUpdate == N||kt[0].size()>0)

                                     break;

                   }

                  if(kt[0].size() == 0){

                            return null;

                   }

                   else{

                            StringBuilder sb = new StringBuilder();

                            //輸出也很有技巧,例如4的話,kt[0]記錄的是2,此時,要輸出100,所以要注意//收尾操作

                            sb.append(1);

                            for(int i = kt[0].pop();;){

                                     int temp = 0;

                                     boolean t = true;

                                     if(kt[0].size()!=0){

                                               temp= kt[0].pop();

                                               t= false;

                                     }

                                     for(int k = i-1;k>temp;k--){

                                               sb.append(0);

                                     }

                                     if(!t)

                                               sb.append(1);

                                     else

                                               sb.append(0);

                                     i = temp;

                                     if(kt[0].size()==0)break;

                            }

                            return sb.toString();

                   }

         }
發佈了70 篇原創文章 · 獲贊 3 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章