程序員面試——位運算

 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進行運算。

最開始想的是用遞歸,不是很好作,並且也是每個這麼搞,時間也太長。

相關文章
相關標籤/搜索