位操作算法的总结(一)

本文参考《程序员面试金典》

1.位操作原理与技巧

第一组:

-x^000..000 = x ;
- x^111..111 = ~x;
- x^x = 0;

第二组:

  • x&000..000 = 0;
  • x&111..111 = x;
  • x&x = x;

第三组:

  • x|000..000 = x;
  • x|111..111 = 111..111;
  • x|x = x;

理解上述三组原理的含义,我们需要记住所有操作都是按位进行的,某一位的运算结果不会影响其余位 。也就是说,只要上述语句对某一位成立,则同样适用于一串位

2.常见的位操作

①:获取某一位

假设获取第r位(从右边开始计数),我们将1开始左移r位,得到形如00010000..类似的串,然后执行位与操作。

代码如下:

public boolean getBit(int num,int location)
{
    return ((num&(1<<location)!=0));
}
②:置位

先将1左移location位,接着用这个值和num进行“位或”操作,这样只会改变i位的数据。

代码如下:

public int setBit(int num,int location)
{
    return num|(1<<location);
}
③:清零

与“置位”操作相反:

public int clearBit(int num,int location)
{
    return num&(~1<<location);
}

//下面是将num的最高位至i位清零的做法如下:
public int clearBitsMSBthroughI(int num,int i)
{
    int mask = (1<<i)-1;
    return num&mask;
}

//将第i位至最后一位清零做法:
public int clearlowertoI(int num,int i )
{
    int mask = ~((1<<i)-1);
    return num&mask;
}

3.一道试题

要求如下:

这里写图片描述

分析:一个串中,增加了一个1,就得减少一个1,而增加1的那个位置如果高于减少的位置,那么是满足条件的略大值,否则就是略小值。其次,我们进行起始操作的位置,肯定是为0的位置。

import java.util.*;

public class CloseNumber {
    public int[] getCloseNumber(int x) {
        // write code here
        int[] a = new int[2];

        a[1] = getbig(x);
        a[0] = getsmall(x);

        return a;

    }

    public int getbig(int x)
        {
        int c0 = 0;
        int c11= 0;
        int temp1 = x;
        int temp2 = x;
        //得到拖尾0的个数
        while((temp1&1)==0&&(temp1!=0))
            {
            c0++;
            temp1>>=1;
        }
        //得到拖尾0左边1的个数
        while(((temp1&1)==1)&&(temp1!=0))
            {
            c11++;
            temp1>>=1;
        }

        int p  =c0+c11;

        temp2|=(1<<p);  //最右边非拖尾0置为1

        temp2&=~((1<<p)-1);//p右方所有位清零

        temp2|=(1<<(c11-1))-1;

        return temp2;

    }

    public int getsmall(int x)
        {

        int temp1 = x;
        int temp2 = x;

        int c1 = 0;//拖尾1的个数
        int c00 = 0;//拖尾1左边连续0的个数

        while((temp1&1)==1){

            c1++;
            temp1>>=1;

        }

        while((temp1&1)==0&&(temp1!=0)){
            c00++;
            temp1>>=1;
        }

        int p = c1+c00;

        temp2&=((~0)<<(p+1));

        int mask = (1<<(c1+1))-1;

        temp2|=mask<<(c00-1);

        return temp2;        

    }
}

源码地址:我的github

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值