位运算的一些技巧

清除最右边的‘1’ n & ( n − 1 ) n\&(n-1) n&(n1)

给定一个整数,计算其二进制表示中‘1’的个数

int popCount(uint64 n){
	int c = 0;
	while(n){
		n &= (n-1);
		c++;
	}
}
  • n & ( n − 1 ) n\&(n-1) n&(n1) 操作能清除n的最右边的’1’

判断一个数是否是2的幂

int isPower(uint64 n){
	return n&(n-1) == 0;
}
  • 2的幂次方的数,其二进制表示中,只有一个1,故只要判断n的二进制表示中是否只有一个‘1’即可。

获取最右边的’1’ n & ( − n ) n\&(-n) n&(n)

a = n & ( − n ) a = n\&(-n) a=n&(n),可以获取到最右边的‘1’,例如: n = 10 = 0b 01010, -n = 0b10110,a = 0b00010

XOR 操作

数组中的数只有一个出现odd次,其他都是even次,找出出现一次的数

int findOdd(vector<int>& nums){
	int res = 0; 
	for(int i = 0; i < nums.size(); ++i){
		res ^= nums[i];
	}
	return res;
}

计算 从1到n的xor值

Number Binary-Repr XOR-from-1-to-n
1 1 [0001]
2 10 [0011]
3 11 [0000] <----- We get a 0
4 100 [0100] <----- Equals to n
5 101 [0001]
6 110 [0111]
7 111 [0000] <----- We get 0
8 1000 [1000] <----- Equals to n
9 1001 [0001]
10 1010 [1011]
11 1011 [0000] <------ We get 0
12 1100 [1100] <------ Equals to n

long computeXOR(int n){
	switch(n&3){
		case 0: return n;
		case 1: return 1;
		case 2: return n+1;
		case 3: return 0;
	}
}

查找缺失的数字

  • 给定n-1大小的数组,存放的数字范围:[1,n],且没有重复的,找到缺失的数字
  • a = a0 ^ a1 ^ a2 ^ … ^ an,b = a0 ^ a1 ^ a2 ^ … ^ an-1;
  • a^b = an
int getMissingNo(vector<int> & nums){
	int x1 = nums[0];
	int x2 = 1;
	for(int i = 1; i < nums.size(); ++i){
		x1 ^= nums[i];
	}
	for(int i = 2; i <= nums.size() + 1; ++i){
		x2 ^= i;
	}
	return x1^x2
}

给定范围,查找缺失的数字

  • 给定一个数组 array,其最小值称为 smallest,数组长度为n,则 i ∈ [ s m a l l e s t , s m a l l e s t + n ] , w h e n i ∈ a r r a y , i\in[smallest,smallest+n],when i\in array, i[smallest,smallest+n],wheniarray,,其中每个数字都不相同
int getMissingNo(vector<int>& nums){
	int smallest = *std::min_element(nums.begin(),nums.end());
	int x1 = nums[0];
	int x2 =smallest;
	for(int i = 1;i < nums.size();++i){
		x1 ^= nums[i];
	}
	for(int i = 1; i <= nums.zie(); ++i){
		x2 ^= i+smallest;
	}
	return x1 ^ x2;
}

给定排序数组,每个数字都不相同,且每个数字的范围是[0,m-1],m>n,找到数组中最小的确实数字

Input: {4, 5, 10, 11}, n = 4, m = 12
Output: 0

Input: {0, 1, 2, 3}, n = 4, m = 5
Output: 4

Input: {0, 1, 2, 3, 4, 5, 6, 7, 10}, n = 9, m = 11
Output: 8

线性查找
int findSmallestMissingNo(std::vector<int>& nums,int l,int r,int c,int m){
    if(l > r || nums[l] != c){
        return c;
    }
    return findSmallestMissingNo(nums,l+1,r,c+1,m);
    
}
二分查找
  • 对 0n-1进行二分查找,认为数组中的元素和0n 对应,
int findSmallestMissingNo(vector<int>& nums,int l,int r){
	if(l > r) return r+1;
	if(l != nums[l]) return l;
	int mid = (l+r)/2;
	if(mid == nums[mid])
		return findSmallestMissingNo(nums,mid+1,r);
	else 
		return findSmallestMissingNo(nums,l,mid);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值