左神算法课笔记异或运算

异或

性质

左神算法课笔记异或运算_第1张图片

异或运算性质:1. N^0=N 2.N^N=0

满足交换律结合律 3.a^b=b^a 4.(a^b)^c=a^b^c 简证:异或运算与运算顺序无关 只要是偶数个1就为0 奇数个1则为1。

题目

1.位运算来交换

用位运算来交换效率比传统算法更高

#include 

int main() {
    int a = 16;
    int b = 603;

    a = a ^ b;
    b = a ^ b;
    a = a ^ b;

    std::cout << "a: " << a << " b: " << b << std::endl;

    return 0;
}

左神算法课笔记异或运算_第2张图片

 需要注意的是交换不能指向同一块内存 否则就会被刷成0

2.打印数组中只有一种数出现奇数次的数 

其余数出现偶数次 全部异或成0 剩下的数是奇数次

void printOddNum(vector &arr) {
	int eor = 0;
	for (int i = 0; i < arr.size() ; i++) {
		eor ^= arr[i];
	}
	cout << eor;
}

 3.提取整型的数最右边的1

取反+1就是自己的相反数 即按位与上自己的相反数

左神算法课笔记异或运算_第3张图片

 4.一个数组有两种数出现奇数次 其他数出现偶数次

打印这两个奇数

思路:a,b地位对等 其实都一样

先用eor去异或每个数 得到eor=a^b 再分离a,b

将所有的数分成最右位为1和0两组 eor'去异或最右位为1的所有数 得到a

再用eor异或eor'得到b

左神算法课笔记异或运算_第4张图片

void printOddNum2(vector& arr) {
	int eor = 0;
	for (int i = 0; i < arr.size() - 1; i++) {
		eor ^= arr[i];
	}
		int rightone = eor & (~eor + 1);//提取最右的1
		int eor2 = 0;
		for (int i = 0; i < arr.size() ; i++) {
			if ((arr[i] & rightone) != 0)//与这个数在此位置上一定是1的数(最右位为1的数)
				eor2 ^= arr[i];
	}
		cout << eor2 <<" "<<( eor ^ eor2);
}

5.一种数出现K次 另一种出现M次

M>1 K

分析:创建一32位数组记录每个数每一位二进制位上的和 如果模m等于1 说明那一种数在该位是1

再用按位或取出该数

int onlyKTimes(vector& arr, int k, int m) {
	int t[32] = { 0 };
	for (int num : arr) {
		for (int i = 0; i <= 31; i++) {
			if ((num >> i) & 1)//t[i]i位置的1出现几次
				t[i]++;
		}
	}
	int ans = 0;
	for (int i = 0; i < 32; i++) {
		if (t[i] % m)
			ans |= (1 << i);

	}
}

再水一题

左神算法课笔记异或运算_第5张图片

 与题5弱化版 思路一样

左神算法课笔记异或运算_第6张图片

 

class Solution {
public:
    int singleNumber(vector& nums) {
       int bitarry[32]={0};
       for(int val:nums){
           for(int i=0;i<32;i++){
               if(val&(1<

你可能感兴趣的:(笔记,c++)