5.1 二進制插入html
有兩個32位整數n和m,請編寫算法將m的二進制數位插入到n的二進制的第j到第i位,其中二進制的位數從低位數到高位且以0開始。java
給定兩個數int n和int m,同時給定int j和int i,意義如題所述,請返回操做後的數,保證n的第j到第i位均爲零,且m的二進制位數小於等於i-j+1。算法
1024,19,2,6
返回:1100
畫圖——》移位+或數組
import java.util.*; public class BinInsert { public int binInsert(int n, int m, int j, int i) { return n|(m<<j); } }
5.2 二進制小數緩存
有一個介於0和1之間的實數,類型爲double,返回它的二進制表示。若是該數字沒法精確地用32位之內的二進制表示,返回「Error」。app
給定一個double num,表示0到1的實數,請返回一個string,表明該數的二進制表示或者「Error」。函數
0.625
返回:0.101
照着二進制和十進制小數的數學關係作就是了:乘2與1比測試
import java.util.*; public class BinDecimal { public String printBin(double num) { StringBuffer res=new StringBuffer(); res.append("0"); res.append("."); for(int i=0;i<33;i++) { if(i==32) return "Error"; num=num*2; if(num-1==0){ res.append("1"); break; }else if(num-1>0){ res.append("1"); num=num-1; }else{ res.append("0"); } } return res.toString(); } }
固然,有時間能夠試試跟0.5之類的作減法;思路差很少spa
5.3 最接近的數設計
蠻力法都還沒作出來,等腦子清醒一點再作;
5.4 ((n&(n-1))==0)的含義
從特殊到通常再到特殊:A&B==0
5.5 整數轉化
編寫一個函數,肯定須要改變幾個位,才能將整數A轉變成整數B。
給定兩個整數int A,int B。請返回須要改變的數位個數。
10,5
返回:4
計數就好,注意用while
import java.util.*; public class Transform { public int calcCost(int A, int B) { // 直接的思路,直接幹,而後計數就行了嘛 int count=0; int index=0; if (A==B) return count; while (A!=B) { if((A&(1<<index))!=(B&(1<<index))){ count++; A=A^(1<<index); } index++; } return count; } }
細節:用num^(1<<index)來改變某一位的值;
5.6 奇偶位交換
請編寫程序交換一個數的二進制的奇數位和偶數位。(使用越少的指令越好)
給定一個int x,請返回交換後的數int。
10
返回:5
import java.util.*; public class Exchange { public int exchangeOddEven(int x) { // 首先,實現功能,就是從頭開始,兩位兩位的跳 //問題在於如何判斷結束,不如再弄一個數字,慢慢賦值 int[] tmp=new int[2]; //int y=0; //int res=0; int index=0; // int slow=0; tmp[0]=x;tmp[1]=0; while(x!=tmp[1]){ swap(tmp,index); index=index+2; } return tmp[0]; } void swap(int[] tmp,int index) { int first=0; int second=0; int xx=tmp[0]; //int yy=tmp[1]; first=xx&(1<<index); second=xx&(1<<(index+1)); if (first!=0) first=1; if (second!=0) second=1; //先清零再置位 tmp[0]=(tmp[0]&(~(1<<index)))|(second<<index); tmp[0]=(tmp[0]&(~(1<<(index+1))))|(first<<(index+1)); //更新y tmp[1]=(tmp[1]|(first<<index))|(second<<(index+1)); } }
關鍵點在於while的中止條件吧,對於我而言;
巧妙方法:先對全部奇數位操做,再是偶數位,再或一下
return (((x & 0xaaaaaaaa)>>1)) | (((x & 0x55555555)<<1));
5.7 找出缺失的整數
數組A包含了0到n的全部整數,但其中缺失了一個。對於這個問題,咱們設定限制,使得一次操做沒法取得數組number裏某個整數的完整內容。惟一的可用操做是詢問數組中第i個元素的二進制的第j位(最低位爲第0位),該操做的時間複雜度爲常數,請設計算法,在O(n)的時間內找到這個數。
給定一個數組number,即全部剩下的數按從小到大排列的二進制各位的值,如A[0][1]表示剩下的第二個數二進制從低到高的第二位。同時給定一個int n,意義如題。請返回缺失的數。
[[0],[0,1]]
返回:1
沒意思。。不作。。
按照書上的思路:通常的是所有加起來,少那個就是那個;
這個的話,就奇偶缺失來作就行!!!
總結
5.3 和5.8沒搞定,5.7不想作,其餘作完了,對位運算,仍是熟練是第一位的,思路要靈活些,什麼快慢指針,遞歸,數組,字符串均可以用起;
---------------拓展--------------------------
1.1&1.7 見 數組與字符串http://www.cnblogs.com/andy1202go/p/5759047.html
17.1 無緩存交換
請編寫一個函數,函數內不使用任何臨時變量,直接交換兩個數的值。
給定一個int數組AB,其第零個元素和第一個元素爲待交換的值,請返回交換後的數組。
[1,2]
返回:[2,1]
個人思路是直接的公式退出來就好啊:
import java.util.*; public class Exchange { public int[] exchangeAB(int[] AB) { AB[0]=AB[0]+AB[1]; AB[1]=-(AB[1]-AB[0]); AB[0]=AB[0]-AB[1]; return AB; } }
書上的位運算解法沒看懂。。。。
a=a^b; b=a^b;//懂了,b=(a^b)^b=a; a=a^b;
媽蛋,有點厲害!!!
18.1 另類加法
不用加號的加法
主體思路:位運算;
通常:搗騰出進位再進行相加之類的
public class Solution { public int getSum(int a, int b) { int[] array=new int[]{a,b}; getReal(array); int sum=array[0]|array[1]; return sum; } public void getReal(int[] array) { int jinWei=array[0]&array[1]; int mask=~jinWei; int huo=array[0]|array[1]; array[0]=mask&huo; array[1]=jinWei<<1; int state=array[0]&array[1]; if (state!=0){ getReal(array); } } }
進階:高級一點的遞歸
import java.util.*; public class UnusualAdd { public int addAB(int A, int B) { if (A==0) return B; if (B==0) return A; int a=A^B,b=(A&B)<<1; return addAB(a,b); } }
18.4 有幾個2
請編寫一個方法,輸出0到n(包括n)中數字2出現了幾回。
給定一個正整數n,請返回0到n的數字中2出現了幾回。
10
返回:1
通常思路,每個數這麼看下來就好
import java.util.*; public class Count2 { public int countNumberOf2s(int n) { //要所有,看起來就像是遞歸 int count=0; if (n<2) return count; for(int i=2;i<=n;i++) { count+=num2(i); } return count; } int num2(int n){ int count=0; while(n>0){ if (n%10==2){ count++; } n=n/10; } return count; } }
算法複雜度太大,時間太長。
找規律,得下面(我tm還沒搞懂)
import java.util.*; public class Count2 { public int countNumberOf2s(int n) { int result = 0; for(int i=1;i<=n;i*=10) { result+=(n/i+7)/10*i+(n/i%10==2?n%i+1:0) ; } return result; } }
每十倍循環一下,而後對這個十倍中有多少2進行運算。
最開始想的是用遞歸,不是很好作,並且也是每個這麼搞,時間也太長。