关注微信公众号:CodingTechWork,一起学习进步。

文章目录

  • 引言
  • 介绍
    • 概念
    • 运算
      • 同为0
      • 异为1
    • 特性
  • 应用
    • 压缩算法
    • 加密算法
    • 备份文件
    • 判断数据异同
    • 交换数
    • 算法应用:[136. 只出现一次的数字](https://leetcode.cn/problems/single-number/description/)
    • 算法应用:[389. 找不同](https://leetcode.cn/problems/find-the-difference/)
    • 算法应用:寻找2个奇数次的数
  • 总结

引言

  在代码中,我们经常看到一个运算符^,这个运算符叫做异或,相比较于与&和或|这些运算符更不容易记住,下面我们一起学习这个运算符的用法。

介绍

概念

  异或也叫半加运算,不带进位的二进制加法。我们知道,在二进制中1表示真,0表示假。异或的运算法则即为:相同为0,不同为1。一般用或者^来表示异或运算符,我们在代码中还是习惯用^

运算

同为0

0 ^ 0 = 0
1 ^ 1 = 0

异为1

1 ^ 0 = 1
0 ^ 1 = 1

特性

  1. 一个数与本身异或,结果总是为 0
    a ^ a = 0
  2. 一个数与0异或,结果总是其自身
    a ^ 0 = a
  3. 交换性
    a ^ b = b ^ a
  4. 结合性
    (a ^ b) ^ c = a ^ (b ^ c)

应用

压缩算法

  在压缩算法中应用异或去除冗余相同的数据。

加密算法

假设key为密钥,clear_text为明文,使用异或得到密文ciphertext

ciphertext = clear_text ^ key

若要解密,也可通过异或去啊哦做

clear_text = ciphertext ^ key
# 推导:
clear_text = ciphertext ^ key= clear_text ^ key ^ key= clear_text ^ (key ^ key)     #结合性、自身异或为0特性= clear_text ^ 0               #和0异或特性= clear_text

备份文件

假设有file_1file_2两个文件需要备份,可以通过异或进行备份。

back_file = file_1 ^ file_2

源文件只要不同时损坏,都可以还原。

# 还原file_1
file_1 = back_file ^ file_2= file_1 ^ file_2 ^ file_2= file_1 ^ (file_2 ^ file_2)       #结合性、自身异或为0特性= file_1 ^ 0                       #和0异或特性= file_1 # 还原file_2
file_2 = back_file ^ file_1= file_1 ^ file_2 ^ file_1= file_1 ^ file_1 ^ file_2    #交换性、自身异或为0特性= 0 ^ file_2                  #和0异或特性= file_2

判断数据异同

# a和b相同
(a ^ b) == 0# a和b不同
(a ^ b) != 0

  现在想想给你两个几乎一摸一样的找茬茬点状图(密集恐惧症的那种),怎么找茬?就可以使用异或进行去重,剩下的就是不一样的数据。

交换数

原本需要临时变量的交换数代码

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

使用异或无需临时变量的交换数代码

    private 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];}

是不是有点绕?我们推导一下

//假设arr[i] = a, arr[j]=b
1. arr[i] = arr[i] ^ arr[j]= a ^ b
此时arr[i] = a ^ b, 而arr[j] = b不变。
2. arr[j] = arr[i] ^ arr[j]= a ^ b ^ b= a ^ (b ^ b)= a ^ 0= a
此时arr[i] = a ^ b不变,而arr[j] = a。
3. arr[i] = arr[i] ^ arr[j]= a ^ b ^ a= a ^ a ^ b= 0 ^ b= b
此时arr[i] = b, arr[j] = a,交换了位置

算法应用:136. 只出现一次的数字

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。说明:你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?示例 1:输入: [2,2,1]
输出: 1
示例 2:输入: [4,1,2,1,2]
输出: 4

这种题目,我们就可以使用异或的如下两个特性进行求解:

  1. 一个数与本身异或,结果总是为 0
  2. 一个数与0异或,结果总是其自身
package com.test.selfcoding.algorithm;/*** @ClassNAME SingleNumber* @Description TODO* @Author Andya* @Date 2022/5/21 17:01* @Version 1.0*/
public class SingleNumber {public static int singleNumber(int[] nums) {int ans = nums[0];for (int i = 1; i < nums.length; i++) {//使用异或^运算//1. 一个数与本身异或,结果总是为0//2. 一个数与0异或,结果总是其自身ans = ans ^ nums[i];}return ans;}public static void main(String[] args) {int[] nums = {4,1,2,1,2};System.out.println(singleNumber(nums));   //结果:4}}

算法应用:389. 找不同

package com.test.selfcoding.algorithm;/*** @ClassNAME FindTheDifference* @Description TODO* @Author Andya* @Date 2022/5/21 17:25* @Version 1.0**/
public class FindTheDifference {/*** 使用异或* @param s* @param t* @return*/public static char findTheDifferenceWithXOR(String s, String t) {int ans = 0;for (int i = 0; i < s.length(); i++) {ans ^= s.charAt(i);}// 此时ans将s字符串中的所有字符拼接起来了for (int j = 0; j < t.length(); j++) {ans ^=  t.charAt(j);}return (char)ans;}/*** 使用位计数法* @param s* @param t* @return*/public static char findTheDifferenceWithCount(String s, String t) {// 26个字母大小的数组int[] letter = new int[26];for (int i = 0; i < s.length(); i++) {char sChar = s.charAt(i);//对应字符位置的数值+1letter[sChar - 'a']++;}for (int j = 0; j < t.length(); j++) {char tChar = t.charAt(j);//对应字符位置的数值-1letter[tChar - 'a']--;//找到负数的则为不同if (letter[tChar - 'a'] < 0) {return tChar;}}return ' ';}/*** 使用ASCII码计算* @param s* @param t* @return*/public static char findTheDifferenceWithASCII(String s, String t) {//将字符串s和t中每个字符的ASCII码的值求和,得到asciiS和asciiTint asciiS = 0, asciiT = 0;for (int i = 0; i < s.length(); i++) {asciiS += s.charAt(i);}for (int j = 0; j < t.length(); j++) {asciiT += t.charAt(j);}return (char) (asciiT - asciiS);}public static void main(String[] args) {String s = "abcdef";String t = "abcdfeg";System.out.println(findTheDifferenceWithXOR(s, t));System.out.println(findTheDifferenceWithCount(s, t));System.out.println(findTheDifferenceWithASCII(s, t)); //结果:g}}

算法应用:寻找2个奇数次的数

package com.test.selfcoding.algorithm;import java.util.Arrays;/*** @ClassNAME Find2OddNumbers* @Description TODO* @Author Andya* @Date 2022/5/21 21:51* @Version 1.0*/
public class Find2OddNumbers {//寻找一个数组中仅有的2个奇数次的数,假设a,b,c,c,d,d,则a和b即为要找的结果public static int[] find2OddNumbers(int[] arr) {//eor = a ^ bint eor = 0;for (int cur : arr) {eor ^= cur;}//若res1 = b 则,res2 = eor ^ res1//找到二进制最右边的1,取非,加1,再与自身// eor =   111010010// ~eor =  000101101//~eor+1 = 000101110//eor & (~eor+1) = 000000010int right = eor & (~eor + 1);int onlyOne = 0;for (int cur : arr) {//取一半,此二进制位为0或者为1,即为一半if ((cur & right) == 1) {onlyOne ^= cur;}}return new int[] {onlyOne, eor ^ onlyOne} ;}public static void main(String[] args) {int[] arr = new int[] {1, 2, 3, 4, 2, 1, 3, 5, 4, 6, 7, 7};System.out.println(Arrays.toString(find2OddNumbers(arr))); //结果:[5,6]}}

总结

  这个运算符之前没有注意到,也是在一个视频中无意看到,于是便学习总结出来,发现这个小小的运算符应用广泛且有趣。

参考
leetcode官网
百度百科

Java—异或运算^的使用详解相关推荐

  1. java多线程中的join方法详解

    java多线程中的join方法详解 方法Join是干啥用的? 简单回答,同步,如何同步? 怎么实现的? 下面将逐个回答. 自从接触Java多线程,一直对Join理解不了.JDK是这样说的:join p ...

  2. 2017年 第08届 蓝桥杯 Java B组 决赛真题详解及小结

    ​​​​​蓝桥杯 Java B组 省赛决赛 真题详解及小结汇总[2013年(第4届)~2020年(第11届)] 第11届 蓝桥杯-第1.2次模拟(软件类)真题-(2020年3月.4月)-官方讲解视频 ...

  3. java的String类源码详解

    java的String类源码详解 类的定义 public final class Stringimplements java.io.Serializable, Comparable<String ...

  4. java集合框架史上最详解(list set 以及map)

    title: Java集合框架史上最详解(list set 以及map) tags: 集合框架 list set map 文章目录 一.集合框架总体架构 1.1 集合框架在被设计时需满足的目标 1.2 ...

  5. Java中的异常和处理详解

    Java中的异常和处理详解 参考文章: (1)Java中的异常和处理详解 (2)https://www.cnblogs.com/lulipro/p/7504267.html 备忘一下.

  6. java string()函数_转载java String.split()函数的用法详解

    转载java String.split()函数的用法详解 如果您发现本文排版有问题,可以先点击下面的链接切换至老版进行查看!!!在java.lang包中有String.split()方法的原型是: p ...

  7. 2015年 第06届 蓝桥杯 Java B组 决赛真题详解及小结

    蓝桥杯 Java B组 省赛决赛 真题详解及小结汇总[2013年(第4届)~2020年(第11届)] 第11届 蓝桥杯-第1.2次模拟(软件类)真题-(2020年3月.4月)-官方讲解视频 说明:大部 ...

  8. 2016年 第07届 蓝桥杯 Java B组 决赛真题详解及小结

    蓝桥杯 Java B组 省赛决赛 真题详解及小结汇总[2013年(第4届)~2020年(第11届)] 第11届 蓝桥杯-第1.2次模拟(软件类)真题-(2020年3月.4月)-官方讲解视频 说明:大部 ...

  9. 2018年 第09届 蓝桥杯 Java B组 决赛真题详解及小结

    蓝桥杯 Java B组 省赛决赛 真题详解及小结汇总[2013年(第4届)~2020年(第11届)] 第11届 蓝桥杯-第1.2次模拟(软件类)真题-(2020年3月.4月)-官方讲解视频 说明:大部 ...

最新文章

  1. 从海外IDC四大标签来看国内IDC公司估值差异问题
  2. 列表查询,添加功能---JSP,servlet
  3. 图论解油瓶分油问题_一个很有趣的de novo图论算法
  4. Ubuntu下apt-get方式Git的安装、配置和更新
  5. springboot和springcloud及常用注解积累
  6. 解决 xshell 上面 zsh 的 home end 无效问题
  7. mysql 名次语法规则_Mysql排名问题
  8. 函数计算机怎么算开根号,excel开根号公式怎么计算(详解excel开根号公式函数)...
  9. lumion材质系统室内渲染6.3
  10. 冷暖自知!史玉柱:巨人失败时,找一圈朋友借钱被拒,但幸亏如此
  11. 跑道标识和那些复杂的灯光系统 and 简介、编号、参数、标志及数量 and 飞机跑道标准与参数...
  12. 不缺流量的罗永浩、李佳琦们,为啥深耕企业微信社群?
  13. html调色盘字符,油画基础知识:调色盘最详细讲解
  14. 谷粒商城--SPU和SKU(属性分组、规格参数、销售属性)
  15. 【PyQt】Qt中QMainWindow, QWidget以及QDialog的区别和选择
  16. 容易让人没朋友的python整蛊小程序,纯属娱乐慎用
  17. Makefile基础教程
  18. 电子科技大学《图论及其应用》复习总结--第三章 图的连通性
  19. SQLyog错误号码
  20. 猿创征文 | 实验一 单片机keil51软件使用及IO控制

热门文章

  1. C语言实现字符串压缩
  2. 利用VTP协议实现交换机 VLAN配置的一致性
  3. 摸鱼加速小能手,实用笔刷快拿走
  4. 在Ubuntu中添加和删除PPA的软件源
  5. C语言中switch的用法
  6. SpringBoot使用SpringDataJPA通过@Query注解多对多分页查询
  7. 对于LM法和信赖域的理解
  8. WebMatrixRazor建站系列之WebMatrix介绍
  9. 汤晓丹的第四版计算机操作系统--第七章总结概述
  10. 操作系统-先进先出和最近最久未使用算法-C语言