Java—异或运算^的使用详解
关注微信公众号: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
特性
- 一个数与本身异或,结果总是为 0
a ^ a = 0
- 一个数与0异或,结果总是其自身
a ^ 0 = a
- 交换性
a ^ b = b ^ a
- 结合性
(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_1
和file_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
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—异或运算^的使用详解相关推荐
- java多线程中的join方法详解
java多线程中的join方法详解 方法Join是干啥用的? 简单回答,同步,如何同步? 怎么实现的? 下面将逐个回答. 自从接触Java多线程,一直对Join理解不了.JDK是这样说的:join p ...
- 2017年 第08届 蓝桥杯 Java B组 决赛真题详解及小结
蓝桥杯 Java B组 省赛决赛 真题详解及小结汇总[2013年(第4届)~2020年(第11届)] 第11届 蓝桥杯-第1.2次模拟(软件类)真题-(2020年3月.4月)-官方讲解视频 ...
- java的String类源码详解
java的String类源码详解 类的定义 public final class Stringimplements java.io.Serializable, Comparable<String ...
- java集合框架史上最详解(list set 以及map)
title: Java集合框架史上最详解(list set 以及map) tags: 集合框架 list set map 文章目录 一.集合框架总体架构 1.1 集合框架在被设计时需满足的目标 1.2 ...
- Java中的异常和处理详解
Java中的异常和处理详解 参考文章: (1)Java中的异常和处理详解 (2)https://www.cnblogs.com/lulipro/p/7504267.html 备忘一下.
- java string()函数_转载java String.split()函数的用法详解
转载java String.split()函数的用法详解 如果您发现本文排版有问题,可以先点击下面的链接切换至老版进行查看!!!在java.lang包中有String.split()方法的原型是: p ...
- 2015年 第06届 蓝桥杯 Java B组 决赛真题详解及小结
蓝桥杯 Java B组 省赛决赛 真题详解及小结汇总[2013年(第4届)~2020年(第11届)] 第11届 蓝桥杯-第1.2次模拟(软件类)真题-(2020年3月.4月)-官方讲解视频 说明:大部 ...
- 2016年 第07届 蓝桥杯 Java B组 决赛真题详解及小结
蓝桥杯 Java B组 省赛决赛 真题详解及小结汇总[2013年(第4届)~2020年(第11届)] 第11届 蓝桥杯-第1.2次模拟(软件类)真题-(2020年3月.4月)-官方讲解视频 说明:大部 ...
- 2018年 第09届 蓝桥杯 Java B组 决赛真题详解及小结
蓝桥杯 Java B组 省赛决赛 真题详解及小结汇总[2013年(第4届)~2020年(第11届)] 第11届 蓝桥杯-第1.2次模拟(软件类)真题-(2020年3月.4月)-官方讲解视频 说明:大部 ...
最新文章
- 从海外IDC四大标签来看国内IDC公司估值差异问题
- 列表查询,添加功能---JSP,servlet
- 图论解油瓶分油问题_一个很有趣的de novo图论算法
- Ubuntu下apt-get方式Git的安装、配置和更新
- springboot和springcloud及常用注解积累
- 解决 xshell 上面 zsh 的 home end 无效问题
- mysql 名次语法规则_Mysql排名问题
- 函数计算机怎么算开根号,excel开根号公式怎么计算(详解excel开根号公式函数)...
- lumion材质系统室内渲染6.3
- 冷暖自知!史玉柱:巨人失败时,找一圈朋友借钱被拒,但幸亏如此
- 跑道标识和那些复杂的灯光系统 and 简介、编号、参数、标志及数量 and 飞机跑道标准与参数...
- 不缺流量的罗永浩、李佳琦们,为啥深耕企业微信社群?
- html调色盘字符,油画基础知识:调色盘最详细讲解
- 谷粒商城--SPU和SKU(属性分组、规格参数、销售属性)
- 【PyQt】Qt中QMainWindow, QWidget以及QDialog的区别和选择
- 容易让人没朋友的python整蛊小程序,纯属娱乐慎用
- Makefile基础教程
- 电子科技大学《图论及其应用》复习总结--第三章 图的连通性
- SQLyog错误号码
- 猿创征文 | 实验一 单片机keil51软件使用及IO控制