位运算相关题目

Posted ych9527

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了位运算相关题目相关的知识,希望对你有一定的参考价值。

插入

给定两个整型数字 N 与 M,以及表示比特位置的 i 与 j(i <= j,且从 0 位开始计算)。编写一种方法,使 M 对应的二进制数字插入 N 对应的二进制数字的第 i ~ j 位区域,不足之处用 0 补齐。具体插入过程如图所示。

题解:

1.将N的 i-j位置为0,即用N减去N当前位置的值

2.将M左移i位,即将M的最后一位挪到i的位置

3.将两个数相加

class Solution {
public:
    int insertBits(int N, int M, int i, int j) {
        //将N的 i-j位置为0

        for(int k=i;k<=j;k++)
        {
            int num=N&(1<<k);//得到第K位的数为多大
            N-=num;//减去这个数,就是将这个位置,置为0
        }

        return N + (M<<i);
    }
};

整数转换

整数转换。编写一个函数,确定需要改变几个位才能将整数A转成整数B。

题解:

1.两个数进行按位与可以得到不同的位组成的值(注意负数,所以用无符号整形变量接收值)

2.求这个值中1的个数,即为需要改变的位数

3.num&(num-1) 即可去除这个数最后一个1

class Solution {
public:
    int convertInteger(int A, int B) {
        //得到A、B有多少个位不同,即最少需要改变几个位
        //异或得到的位是不同的

        unsigned num=A^B;

        int count=0;
        while(num)
        {
            num&=(num-1);
            count++;
        }
        return count;
    }
};

配对交换

配对交换。编写程序,交换某个整数的奇数位和偶数位,尽量使用较少的指令(也就是说,位0与位1交换,位2与位3交换,以此类推)。

题解:

1.首先得到奇偶位置的比特位
num&(1<<(i)) 不为0,则第i个位置的比特位为1,否则为0

2.比较奇偶位置的比特位,如果相反,则进行操作,否则不进行操作
将第i个位置设置为0:num-=(1<<i)
将第i个之为设置为1: num+=(1<<i)

class Solution {
public:
    int exchangeBits(int num) {
        //得到奇数和偶数的位置是0还是1
        
        for(int i=0;i<31;i+=2)
        {
            int odd=num&(1<<(i+1));//得到奇数位
            int even=num&(1<<i);//得到偶数位

            if(odd==0&&even==0)//两个位置都为0
                continue;
            
            if(even!=0&&odd==0)//偶数位置为1,奇数位置为0
            {
                num-=even;//偶数位置变为0
                num+=(1<<(i+1));//奇数位置变为1
            }
            else if(even==0&&odd!=0)//偶数位置为0,奇数位置为1
            {
                num+=(1<<i);//偶数位置变为1
                num-=(1<<(i+1));//奇数位置变为0
            }
        }
        return num;
    }
};

下一个数

下一个数。给定一个正整数,找出与其二进制表达式中1的个数相同且大小最接近的那两个数(一个略大,一个略小)。

题解:

1.比特位个数相同,又正好大小最接近

2.接近 -> 改变的最少,并且比特位个数要相同

3.变大:将第一个为0的比特位变为1,在这个比特位后的第一个为1的比特位变为0,
然后将此位置后面的
1全部挪到靠右边,0全部挪到靠左边

4.变小:将第一个为1的比特位变为0,将这个位置后面的第一个为0的比特位变为1
然后将此位置的后面的
1全部挪到靠左边,0全部挪到靠右边

5.边界处理:找到的位置不能是符号位

class Solution {
public:
    vector<int> findClosedNumbers(int num) {
        //比特位个数相同,又正好大小最接近

        //接近 ->  改变的最少,并且比特位个数要相同
        //变大:将第一个为0的比特位变为1,在这个比特位后的第一个为1的比特位变为0,
        //然后将此位置后面的1。全部挪到靠右边,0全部挪到靠左边

        //变小:将第一个为1的比特位变为0,将这个位置后面的第一个为0的比特位变为1
        //然后将此位置的后面的1全部挪到靠左边,0全部挪到靠右边

        //边界处理:找到的位置不能是符号位

    vector<int> ret(2,-1);
    //1.获取num的比特位情况
        vector<int> arr(32,0);
        for(int i=0;i<32;i++)
        {
            if(num&(1<<i))//当前位不为0
                arr[i]=1;
        }
    
        vector<int>max(arr);

    //2.求变大的数
        int end=-1;

        for(int i=0;i<32;i++)
        {
            if(max[i]==0&&end!=-1&&i!=31)//找到第一个比特位为0的位置
            {
                max[i]=1;
                max[end]=0;
                break;

            }
            else if(max[i]==1)
            {
                end=i;
            }
        }
        if(arr!=max)//没有找到
        {
            //统计 0-end位置1的个数
            int count=0;
            for(int i=0;i<end;i++)
            {
                if(max[i]==1)
                    count++;
            }
            //将所有的1挪到右边
            for(int i=0;i<end;i++)
            {
                if(count!=0)
                {
                    max[i]=1;
                    count--;
                }
                else
                    max[i]=0;
            }
            //取出比特位组成数字
            int n_max=0;
            for(int i=0;i<32;i++)
            {
                int n=max[i];
                n_max|=(n<<i);
            }
            ret[0]=n_max;
        }
    //3.求变小的数
        end=-1;
        vector<int> min(arr);

        for(int i=0;i<32;i++)
        {
            if(min[i]==1&&end!=-1&&i!=31)//找到第一个比特位为1的位置
            {
                min[i]=0;
                min[end]=1;
                break;
            }
            else if(min[i]==0)
            {
                end=i;
            }
        }
        if(arr!=min)//没有找到
        {
             //统计 0-end位置0的个数
            int count=0;
            for(int i=0;i<end;i++)
            {
                if(min[i]==0)
                    count++;
            }
            //将所有的0挪到右边
            for(int i=0;i<end;i++)
            {
                if(count!=0)
                {
                    min[i]=0;
                    count--;
                }
                else
                    min[i]=1;
            }

            //取出比特位组成数字
            int n_min=0;
            for(int i=0;i<32;i++)
            {
                int n=min[i];
                n_min|=(n<<i);
            }
            ret[1]=n_min;
        }
        return ret;
    }
};

以上是关于位运算相关题目的主要内容,如果未能解决你的问题,请参考以下文章

20194626 自动生成四则运算题第一版报告

算法 | 第5章 位操作相关《程序员面试金典》#yyds干货盘点#

位运算题目

字符串类题目——滑动窗口和递归分治以及一些些位运算的结合

字符的判重--位运算

位运算模板