左神算法学习--异或运算(无进位相加)

异或运算

num1num2num1^num2
000
011
101
110
  • 异或运算:位运算的一种

  • 相同为0 不同为1

  • 可以理解为无进位相加

  • 异或满足交换律,结合律

  • 1^ 2^ 3^ 4^ 5^ 5^ 4^ 3^ 2^ 1 = 1^ 1^ 2^ 2^ 3^ 3^ 4^ 4^ 5^ 5 = 0

在这里插入图片描述

1.交换位置

    public static void swap(int[] arr, int i, int j) {
        arr[i] = arr[i] ^ arr[j];
        arr[j] = arr[i] ^ arr[j];
        arr[i] = arr[i] ^ arr[j];
    }

执行流程解析
a=2;b=3;
a = a ^ b; //a = 2 ^ 3;
b = a ^ b; // b = 2 ^ 3 ^3 = 2;
a = a ^ b; // a = 2 ^ 3 ^ 2 = 3;

  • 这种交换的思想是异或运算(相同为0,不同为1)(1^ 2^ 1 = 2)
  • 两个相同的数异或为0
  • 0和任何数异或还得任意数
  • 快且省空间,计算机毕竟看01更好些
  • 注:这里的交换两个元素的位置不能是同一个位置,i不能等于j

选择排序和冒泡排序都关系到元素的换位置
选择是先找要交换的下标,然后交换;
冒号是相邻比较交换,将大的数据换到后面去;

2.找出不成对的那个数(人生密码)

2.1 只有一种数出现了奇数次,其他的所有数都出现了偶数次,,,请找出出现奇数次的数值

在这里插入图片描述
在这里插入图片描述

#include<stdio.h>
int main() {
    int n,ans=0,x;
    while(scanf("%d",&n)&&n!=0)
    {
    	ans=0;
		if(n==1)
		{
			scanf("%d",&x);
			printf("%d\n",x);      //奇数个元素,如果是一个元素的话,就直接输出
		}
		else{
			for(int i=0;i<n;i++)  //如果是多个元素就做异或运算
    	    {
    			scanf("%d",&x);   //如果a=6,b=6 ,那么a^b的结果就是0(相同为0不同为1)
				ans^=x;          //如果a=0,b=5,那么a^b的结果就是5(0与任何数做异或运算还得任意数)		
			}
			printf("%d\n",ans);
		}
    }
}

输入:

3 8 9 8
5 1 2 1 2 3
0

输出:
在这里插入图片描述

  • 异或运算就像消消乐一样,遇到相同的数就归0 了
    (相同为0,不同为1):是二进制按位运算

1^2=3;
1^3=2;

综上: 1^2 ^1 = 2;
1^ 2 ^ 3 ^ 2^ 5^ 1 = 5;

2.2 有两种出现奇数次的数,和多个出现偶数次的数,找出出现奇数次的那两个数值

    public static void printOaaTimesNum(int[] arr) {
        int eor = 0;
        for (int i : arr) {
            eor ^= i;
        }
        //eor = a ^ b;
        //eor != 0;
        //eor必然有一个位置上是1
        int rightOne = eor & (~eor + 1); //提取出eor二进制最右边的1
        int onlyOne = 0; //eor'
        for (int i : arr) {
            if ((i & rightOne) == 1){  //这里判断等于1或0都是一样的效果
                onlyOne ^= i;
            }
        }
        System.out.println(onlyOne+ " "+(eor ^ onlyOne));
    }

  • 一个数与上(自己取反+1)就是把自己最右边的第一不为0的数取出来
    在这里插入图片描述
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

848698119

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值