成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

送上今年微軟的一道筆試題

開發 開發工具
這里送上一道微軟的筆試題,大家可能會認為這是一個全排列的問題,但是全排列在問題在于不能很好的知道每個數到底排在第幾位,并且時間上肯定是不能通過的,遞歸的效率大家應該都知道。

這里送上一道微軟的筆試題,具體題目如下:

Time Limit: 10000ms

Case Time Limit: 1000ms

Memory Limit: 256MB

 

Description

Consider a string set that each of them consists of {0, 1} only. All strings in the set have the same number of 0s and 1s.

Write a program to find and output the K-th string according to the dictionary order. If s​uch a string doesn’t exist,

or the input is not valid, please output “Impossible”. For example, if we have two ‘0’s and two ‘1’s,

we will have a set with 6 different strings, {0011, 0101, 0110, 1001, 1010, 1100}, and the 4th string is 1001.

 

Input

The first line of the input file contains a single integer t (1 ≤ t ≤ 10000),

the number of test cases, followed by the input data for each test case.

Each test case is 3 integers separated by blank space: N, M(2 <= N + M <= 33 and N , M >= 0),

K(1 <= K <= 1000000000). N stands for the number of ‘0’s, M stands for the number of ‘1’s,

and K stands for the K-th of string in the set that needs to be printed as output.

 

Output

For each case, print exactly one line. If the string exists, please print it, otherwise print “Impossible”.

 

Sample In

3

2 2 2

2 2 7

4 7 47

Sample Out

0101

Impossible

01010111011

其實說了這么多,意思很簡單,就是輸入N個0,M個1.然后求出由M,N個1,0組成的第K大的數。如果不存在則輸出impossible.

初來乍到的,大家可能會認為這是一個全排列的問題,但是全排列在問題在于不能很好的知道每個數到底排在第幾位,并且時間上肯定是不能通過的,遞歸的效率大家應該都知道。

我們可能會想到另外一種解決方案,直接列舉,從最小的000...1111開始,一直列舉到1111..000然后記錄下當前是否是含N個0,M個1。這種方式是最容易理解的了,但是如果數字比較大,比如17個1,17個0,我們且不說這么大的整數不能保存,就這個時間上也不合算啊,雖然他是線性復雜度,但是這個線性數也太大了點。。。

OK,我接下來又想到了是否可以通過樹的遍歷,想了想被我否了。

終于想到了一種方式,就是通過不斷的交換獲得。我們想到,如果從一個第1大的數變成第2大的數,必然要使這個數增大,那么怎么個增大法?才能使得這兩個數是最接近的,也就是說我們只增加了1,而不是中間還存在很多數呢?

那就是從左到右掃描數據,直到遇到10就交換,并且在該1之前的1要和***位的0交換。好的思路已經完全暴露了,我這里就列舉一個例子。

比如5個1,5個0的情況。

我們保存的格式是1111100000(實際數為0000011111),它是最小的數(輸出的時候倒著輸出,這種結構主要為了理解方便)。***的數是0000011111.(記住,是倒著哈!)

當我們要增加的時候在J=5的時候,出現了0,且j=4時,它為1,這樣就交換他們,j=4之前的1和低位的0交換,這里沒有0就不需要交換了。得到1111010000(實際數為0000101111).

當我們出現0011101100(實際數為0011011100)要使數字增加1應該怎么做呢?顯然,還是J=5時出現了0且j-1=4時為1交換他們,并且j=4之前的1和***位的0開始不斷交換,***我們會得到結果:1100011100.(實際數為00111000011).

Ok,說到這里大家應該就完全懂了,且看算法源代碼:[集思廣益,你們有沒有更好的解決方案?]

  1. //M:0的個數,N,1的個數。K要輸出第幾個數。 
  2. bool test(int N,int M,int K){ 
  3.     if(calculateTotalNum(M+N,M)<K)//若實際上的數少于k,返回false,則輸出impossible 
  4.         return false
  5.     int L=M+N,count=1
  6.     bitset<MaxLength> bit; 
  7.     map<int,bitset<MaxLength>> mapStr; 
  8.     for(int i=0;i<M;i++)//初始話最小數,即0都在最左邊比如0011 
  9.         bit[i]=1
  10.     if(K==1){ 
  11.         print(bit,M+N);//輸出 
  12.         return true
  13.     } 
  14.     int j=0;//表示從低位一直搜索到高位,有沒有遇到01,有的話就不斷交換。 
  15.     while(!isLast(bit,M,N)){//沒有搜索到***一個數字 
  16.         if(j>=M+N-1
  17.             j=0;//已經搜索到***位了,這個時候就需要從0位搜索 
  18.         if(1==bit[j]&&0==bit[j+1]){ 
  19.             int right=j-1,left=0
  20.             //從J的前一個搜素,并且該之前的1全部移動到最左邊 
  21.             while(right>=0&&bit[right]==1&&left<right){ 
  22.                 bool temp=bit[right]; 
  23.                 bit[right]=bit[left]; 
  24.                 bit[left]=temp; 
  25.                 right--,left++; 
  26.             } 
  27.             bit[j]=0;//交換0,1 
  28.             bit[j+1]=1
  29.             count++;//統計是第幾個大的數了 
  30.             if(count==K){ 
  31.                 print(bit,M+N); 
  32.                 return true
  33.             } 
  34.             j=0;//重新回過頭來搜素 
  35.         } 
  36.         else 
  37.             j++; 
  38.     } 
  39.     return true
  40.  
  41. int calculateTotalNum(int N,int M){//組合問題,計算一共多少個數。C(M,N)=A(N,N)/(A(M,M)*A(N-M,N-M)) 
  42.     int result=1
  43.     for(int i=1;i<=N;i++) 
  44.         result*=i; 
  45.     for(int i=1;i<=M;i++) 
  46.         result/=i; 
  47.     for(int i=1;i<=N-M;i++) 
  48.         result/=i; 
  49.     return result; 
  50. bool isLast(bitset<MaxLength> bit,int M,int N){ 
  51.     int i=0
  52.     while(i<N&&0==bit[i]) 
  53.         i++; 
  54.     if(i==N) 
  55.         return true
  56.     else 
  57.         return false
  58. void print(bitset<MaxLength> bit,int N){// 
  59.     for(int i=N-1;i>=0;i--) 
  60.         cout<<bit[i]; 
  61.     cout<<"  "

 附上效果截圖:

 [庸男勿擾] 同學提供了一種其他的解決方式,主要是通過遞歸的判斷當前0,1組合生成的個數與K進行比較。

(保證在不減一個0時,生成的組合總數是大于K的,否則return。)

若當前0的個數減一后,生成的總數要大于K,則輸出0,同時0的個數減一,K,1的個數不變。

若當前0的個數減一后,生成的總數小于K,則輸出1,同時1的個數減一,0的個數不變,K=K-當前總數。

遞歸調用。***能得到結果。

代碼 [庸男勿擾] 已經貼出,在回答留言處!

[有一個問題是,我和庸男勿擾在計算總次數的時候都會有溢出的問題,即使用Long long也會溢出的,大家在計算階乘或者組合問題對溢出解決方案有什么好的建議可以給出嗎?] 

原文鏈接:http://www.cnblogs.com/xiaoyi115/p/3696507.html

責任編輯:林師授 來源: 博客園
相關推薦

2021-05-09 19:42:25

筆試題前端算法

2021-04-30 08:22:36

異步求和函數

2024-10-11 17:09:27

2009-06-22 13:43:00

java算法

2011-05-23 11:27:32

面試題面試java

2018-03-06 15:30:47

Java面試題

2009-08-11 10:12:07

C#算法

2023-02-04 18:24:10

SeataJava業務

2012-07-03 09:38:42

前端

2009-08-11 14:59:57

一道面試題C#算法

2021-01-26 13:14:14

js前端map

2021-05-31 07:55:44

smartRepeatJavaScript函數

2017-11-21 12:15:27

數據庫面試題SQL

2022-04-08 07:52:17

CSS面試題HTML

2009-08-11 15:09:44

一道面試題C#算法

2024-03-18 13:32:11

2023-08-01 08:10:46

內存緩存

2010-08-11 11:57:02

微軟筆試題微軟筆試題

2021-03-16 05:44:26

JVM面試題運行時數據

2021-10-28 11:40:58

回文鏈表面試題數據結構
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 午夜久久久 | 91在线免费观看网站 | 99久久免费精品国产男女高不卡 | 精品国产一区二区三区性色av | www.久久99| 日本a视频 | 欧美一区视频 | av大全在线 | 狠狠涩 | 无码日韩精品一区二区免费 | 日韩一区二区视频 | 超碰精品在线观看 | 免费骚视频 | 午夜电影一区二区 | 国产精品国产馆在线真实露脸 | 亚洲一区二区电影在线观看 | 一区二区日本 | 天天艹天天干天天 | 欧美区在线观看 | 一区二视频 | 久久国产婷婷国产香蕉 | 欧美日韩国产一区 | 国产美女久久 | 亚洲人va欧美va人人爽 | 免费一级淫片aaa片毛片a级 | 国产亚洲一区精品 | 天天爽天天操 | 亚洲高清一区二区三区 | 岛国av一区二区 | 国产一区久久精品 | 狠狠躁天天躁夜夜躁婷婷老牛影视 | 色网站在线 | 久久久久久国产精品免费免费狐狸 | 午夜视频一区 | 亚洲一级在线 | 国产成人精品免高潮在线观看 | 免费三级黄| 亚洲精品一区二区冲田杏梨 | 夜夜操天天艹 | 狠狠色综合网站久久久久久久 | 欧美日韩久久久 |