zoukankan      html  css  js  c++  java
  • 程序员面试——位运算

     5.1 二进制插入

    有两个32位整数n和m,请编写算法将m的二进制数位插入到n的二进制的第j到第i位,其中二进制的位数从低位数到高位且以0开始。

    给定两个数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”。

    给定一个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之类的做减法;思路差不多

    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进行运算。

    最开始想的是用递归,不是很好做,而且也是每一个这么搞,时间也太长。

  • 相关阅读:
    Windows 7 x64环境下SDK Manager闪退的解决方法
    Android 开发环境下载地址 -- 百度网盘 adt-bundle android-studio sdk adt 下载
    【智能家居篇】wifi网络结构(下)
    mac 查看python路径
    制作NGUI动态字体
    Mac OS 10.10.3下Apache + mod_wsgi配置【一】
    归档日志
    Cocos2D-X2.2.3学习笔记12(瞬时动作)
    合并两个已经排好序的不等长的数组
    JSON-JSON字符串转换成JSON对象、JSON对象数组、java实体类以及保存到List列表中
  • 原文地址:https://www.cnblogs.com/andy1202go/p/5761098.html
Copyright © 2011-2022 走看看