基本算法学习-1

小白算法学习 1 --位与二进制

基础题部分

按位异或 ^ 的用处
  1. 使特定位翻转

比如:01111010,想使其低4位翻转,即1变为0,0变为1。可以将它与00001111进行∧运算,要使哪几位翻转就将与其∧运算的该几位置为1即可。

  1. 通过按位异或运算,可以实现两个值的交换,而不必使用临时变量。

例如交换两个整数a=3,b=4的值,可通过下列语句实现:

a=a∧b;
b=b∧a;
a=a∧b;
位运算的妙用
  1. 位运算实现加法:
    x^y :相加
    (x&y)<<1 :移位进位
//位运算实现加减法 
#include <stdio.h> 
 
int add(int a, int b)
{
    if(b==0)
        return a;
    else
	{
        int sum = a^b;	//按位异或 
        int carry = (a&b)<<1;	//按位与 	左移 
        return add(sum,carry);
    }
}
 
int negative(int a) {
      return ~a + 1;
  }
int Minus(int a, int b) {
      return add(a, negative(b));
  }
 
int main()
{
	int a = 10, b = 15;
	printf("%d\n",add(a,b));
	printf("%d",Minus(a,b));
	return 0;
}

  1. 位运算实现除法:(乘除同理)
    除法可以缩小步长:
    计算机是一个二元的世界,所有的int型数据都可以用[2^0, 21,…,2{31}]这样一组基来表示(int型最高31位)。不难想到用除数的2{31},2{30},…,22,21,2^0倍尝试去减被除数,如果减得动,则把相应的倍数加到商中;如果减不动,则依次尝试更小的倍数。这样就可以快速逼近最终的结果。
int divide(int a, int b) {

       //结果溢出:返回int最大值
		if (a == INT_MIN&&b == -1)
		{
			return INT_MAX;
		}
		unsigned int ans = 0;
		int sign = (a > 0) ^ (b > 0) ? -1 : 1;  //使用异或记录结果的符号,只有一正一负才为负号
		unsigned int ua = abs(a);//使用无符号数字避免越界
		unsigned int ub = abs(b);//使用无符号数字避免越界

		for (int i = 31; i >= 0; --i)//从最高位开始以为,减少运算
		{
			if ((ua >> i) >= ub)//如果ua右移i位仍大于ub,则ub左移i位一定小于ua,即可以被减
			{
				ua = ua - (ub << i);//减去之后再次对ua进行运算
				ans += 1 << i;//记录当前减去多少次ub
			}
		}
		return sign == 1 ? ans : -ans;
	}

//二进制求相反数需要按位取反再加一

提高题部分

Brian Kernighan 算法

该算法可以被描述为这样一个结论:记 f(x) 表示 x 和 x-1 进行与运算所得的结果(即 f(x)=x & (x−1)),那么f(x) 恰为 x 删去其二进制表示中最右侧的 1 的结果。
tutu
例题1:
tutu

var hammingDistance = function(x, y) {
    let s = x ^ y, ret = 0;
    while(s != 0){
        s &= s - 1;
        ret++;
    }
    return ret;
};

例题2:计算从 00 到 nn 的每个整数的二进制表示中的 11 的数目

利用Brian Kernighan算法,可以在一定程度上进一步提升计算速度。Brian Kernighan算法的原理是:对于任意整数 x,令 x=x & (x−1),该运算将 x 的二进制表示的最后一个 1 变成 0。因此,对 x 重复该操作,直到 x 变成 0,则操作次数即为 x 的「一比特数」。
对于给定的 nn,计算从 00 到 nn 的每个整数的「一比特数」的时间都不会超过 O(logn),因此总时间复杂度为 O(nlogn)。

int count(int x){
        int co=0;
        while(x>0){
            x &= x-1;
            co++;
        }
        return co;
    }
    vector<int> countBits(int n) {
            vector<int> Bits(n+1);
            for(int i=0;i<=n;i++){
                Bits[i]=count(i);
            }
        return Bits;
    }

例题3:给定整数n,判断其是否为2的幂次方

var isPowerOfTwo = function(n) {
    return n > 0 && (n&(n-1)) == 0;
};//js
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值