算法面試題-今日頭條2017客戶端工程師實習生筆試題4:或與加


今日頭條2017客戶端工程師實習生筆試題

題目:

這個題做到最后,時間不是很夠,題目內容比較簡單,求出第k個正整數符合x+y=x|y,然而這個k的取值范圍非常大(k<=2000000000),所以可以不用考慮窮舉法,當然,時間不夠的話寫個窮舉試試運氣也可以。

窮舉法:

 1 import java.util.Scanner;
 2  
 3 /**
 4  * Created by Administrator on 2016/9/6.
 5  */
 6  
 7 public class Main {
 8     public static void main(String[] args) {
 9         Scanner scanner = new Scanner(System.in);
10         int x = scanner.nextInt();
11         int k = scanner.nextInt();
12         int n = 0;
13         int result = 0;
14         for (int i = 1; i <= 2000000000; i++) {
15             if ((x + i) == (x | i)) {
16                 n += 1;
17             }
18             if (n == k) {
19                 result = i;
20                 break;
21             }
22         }
23         System.out.println(result);
24     }
25 }

這里提交會提示超時,所以這個算法是不行的,比較循環的次數太多。

第一個想法是能不能減少循環次數,但是考慮到要求第k個,也就是不能省略掉其中一些否則會遺漏,所以只能考慮能否不使用循環求得。

因為這里用到了位運算,所以可以通過二進制來演算一下。

假設數據x=5,k=1的時候,y=2,分別用二進制進行表示:

5D = 0101B

2D = 0010B

7D = 0111B

這里其實已經可以發現規律了。

x+y是把x和y每一個二進制位進行相加,1+1就進位

x|y則是每個二進制位置對應的進行或運算(有1得1)

這個題目中,x的值是固定的,也就是x的二進制數中1的位置和數目是固定的,所以進行或運算的時候,結果中對應的位上都應該是1

現在考慮相加的情況,假設y與x中某一對應的位置都是1,就需要進行進位,也就是這個位置會變成0,顯然x+y!=x|y。

考慮x中0的影響,因為在相加或者或運算的時候,0都不會影響到運算結果,所以結論很顯然:

yB的對應於xB上所有為1的位均為0,則必有x+y=x|y。

現在考慮如何得到第k個。

因為有上面的規律,我們可以得知,y中為1的位只能對應於x中為0的位。

這里就很簡單了,我們只需要求出k的二進制值,並且把這個二進制的值從低位逐個填入x為0的位即可得到相加的結果。

如:5+2=5|2=7 k=1

5D = 0101B

1D = 0001B

我們把1的二進制填入至x的二進制為0的地方則能得到0111B,也就是十進制的7。7-5=2,就能得到y的值。

再舉一個例子:x=5, k=2

5D = 0101B

2D = 0010B

把2的二進制從低位開始填入5的二進制數中為0的地方,即可得到1101B,也就是13,所以y=13-5=8。

實際上,我們只需要把x中對應為1的地方改為1,就能直接得到y的值,相當於減去x。

所以我們在實際構造的時候,可以這樣做:

逆序遍歷x的每一位

  如果為1,則往結果的頭部填充一個0(減法)

  否則將k中的最后一位填入結果的頭部,並退出k的最后一位,此時如果k已經為空,則退出遍歷。

  判斷x是否已經遍歷完,如果是,將k剩余的位一次填充到結果的頭部。

 

AC代碼:

 1 import java.util.Scanner;
 2 
 3 /**
 4  * Created by Administrator on 2016/9/6.
 5  */
 6 
 7 public class Main {
 8     public static void main(String[] args) {
 9         Scanner scanner = new Scanner(System.in);
10         int x = scanner.nextInt();
11         int k = scanner.nextInt();
12         String x_str = Integer.toBinaryString(x);
13         String k_str = Integer.toBinaryString(k);
14         StringBuilder sb = new StringBuilder();
15         int pointer = k_str.length() - 1;
16         for (int i = x_str.length() - 1; i >= 0; i--) {
17             if (x_str.charAt(i) == '1') {
18                 sb.insert(0, "0");
19             } else {
20                 sb.insert(0, k_str.charAt(pointer));
21                 pointer -= 1;
22                 if (pointer < 0) {
23                     break;
24                 }
25             }
26             if (i == 0 && pointer >= 0) {
27                 sb.insert(0, k_str.substring(0, pointer + 1));
28             }
29         }
30         System.out.println(Long.parseLong(sb.toString(), 2)); // 使用Long是因為結果可能會超過Integer的表示范圍
31     }
32 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM