认识异或运算

异或运算就记成无进位相加

0 1 1

1 0 1

1 1 0

异或运算满足交换律和结合律

同样一批数,不管选择什么样的顺序做异或运算,最后结果一定是一个

如何不使用额外的变量交换两个数

1)a = a ^ b

2) b = a ^ b

3) a = a ^ b

比如说a = 甲,b = 乙

1)a = 甲 ^ 乙,b = 乙

2)b = 甲^乙^乙,a = 甲 ^ 乙

3)a = 甲^乙^甲,b = 甲

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

能够使用异或运算的前提是,两个数的交换,不能是同一个位置

只有两个内存区域是分开的,你才能这么玩

如果要在arr 里交换 i位置跟j位置的数, 如果i位置和j位置是同一个位置, 则用异或交换是错误的你是一个内存区域,你跑完这三行代码之后,就把自己刷成0

一个数组中有一种数出现了奇数次,其他数都出现了偶数次,怎么找到并打印这个数

用eor异或所有人, 把最后结果留在自己身上, 这么干完一遍之后,最后你返回eor的值就是那个出现了奇数次的数
public static void printOddTimesNum1(int[] arr){int eor = 0;for(int i = 0;i < arr.length;i++){eor ^= arr[i];    }
}

把一个int类型的数,提取出最右侧的1出来

int rightOne = eor & (~eor + 1);

例如:

eor = 0110 1110 0100 0000

~eor = 1001 0001 1011 1111

~eor+1 = 1001 0001 1100 0000

& = 0000 0000 0100 0000

此时的结果就是最右侧的1

一个数组中有两种数出现奇数次,其他数出现偶数次,怎么找到并打印这个数

public static void printOddTimesNum1(int[] arr){int eor = 0;for(int i = 0;i < arr.length;i++){eor ^= arr[i];//此时得到的eor = a^b,偶数次都为0了,所以最后就剩a^b    }//又因为a != b,a ^ b != 0,所以a,b两个数中肯定有一位不相同int rightOne = eor & (~eor + 1);//提取出最右侧数int onlyOne = 0;//循环得到的结果是a or bfor(int i = 0;i < arr.length;i++){if((arr[i] & rightOne) != 0){onlyOne ^= arr[i];        }    }sout(onluOne + (eor ^ onlyOne));}

一个数组中有一种数出现K次,其他数都出现了M次, M > 1, K < M 找到,出现了K次的数, 要求,额外空间复杂度O(1),时间复杂度O(N)

题意

题解

准备一个长度为 32 的数组, 固定长度的数组, 依然额外空间复杂度O(1)第一步: 把所有数字二进制状态每个位置的1都累加到t里

任何一个整数都可以转成数组形式的二进制状态

如果 a, b, c, 出现7次, d出现3次, 如果第0位不是7的整数倍, 意味着d 在 0位一定是1, 如果是7的整数倍, 意味着d 在 0位一定不是1, 因为K>M

1出现7次, 3出现7次, 5出现3次, 二进制表达在第零位相加为17次, 不是7的整数倍,说明你要求的这个出现了3次的数在第零位肯定是1通过每一位上是否是7的整数倍,来把出现较小次数的数在这位是不是1确定下来

- 可以最后通过每一位上是否是 M 的整数倍这件事就把那个出现了较小次数的数给他依次给弄出来- 如果我们在某一个变量发现 1 的数量不能够被 M 整除,说明我要找的那个数,在这一位它一定是 1 状态。- 如果我们在某一个变量发现 1 的数量能够被 M 整除,说明我要找的那个数,在这一位它一定是0 状态。

如果零这个数出现K次, 则需要特殊处理

public class Code03_KM {public static int test(int[] arr, int k, int m) {HashMap<Integer, Integer> map = new HashMap<>();for (int num : arr) {if (map.containsKey(num)) {map.put(num, map.get(num) + 1);} else {map.put(num, 1);}}for (int num : map.keySet()) {if (map.get(num) == k) {return num;}}return -1;}public static HashMap<Integer, Integer> map = new HashMap<>();// 请保证arr中,只有一种数出现了K次,其他数都出现了M次public static int onlyKTimes(int[] arr, int k, int m) {if (map.size() == 0) {mapCreater(map);}int[] t = new int[32];// t[0] 0位置的1出现了几个// t[i] i位置的1出现了几个for (int num : arr) {while (num != 0) {int rightOne = num & (-num);t[map.get(rightOne)]++;num ^= rightOne;}}int ans = 0;for (int i = 0; i < 32; i++) {if (t[i] % m != 0) {if (t[i] % m == k) {ans |= (1 << i);} else {return -1;}}}if (ans == 0) {int count = 0;for (int num : arr) {if (num == 0) {count++;}}if (count != k) {return -1;}}return ans;}public static void mapCreater(HashMap<Integer, Integer> map) {int value = 1;for (int i = 0; i < 32; i++) {map.put(value, i);value <<= 1;}}public static int[] randomArray(int maxKinds, int range, int k, int m) {int ktimeNum = randomNumber(range);// 真命天子出现的次数int times = Math.random() < 0.5 ? k : ((int) (Math.random() * (m - 1)) + 1);// 2int numKinds = (int) (Math.random() * maxKinds) + 2;// k * 1 + (numKinds - 1) * mint[] arr = new int[times + (numKinds - 1) * m];int index = 0;for (; index < times; index++) {arr[index] = ktimeNum;}numKinds--;HashSet<Integer> set = new HashSet<>();set.add(ktimeNum);while (numKinds != 0) {int curNum = 0;do {curNum = randomNumber(range);} while (set.contains(curNum));set.add(curNum);numKinds--;for (int i = 0; i < m; i++) {arr[index++] = curNum;}}// arr 填好了for (int i = 0; i < arr.length; i++) {// i 位置的数,我想随机和j位置的数做交换int j = (int) (Math.random() * arr.length);// 0 ~ N-1int tmp = arr[i];arr[i] = arr[j];arr[j] = tmp;}return arr;}// [-range, +range]public static int randomNumber(int range) {return (int) (Math.random() * (range + 1)) - (int) (Math.random() * (range + 1));}public static void main(String[] args) {int kinds = 5;int range = 30;int testTime = 100000;int max = 9;System.out.println("测试开始");for (int i = 0; i < testTime; i++) {int a = (int) (Math.random() * max) + 1; // a 1 ~ 9int b = (int) (Math.random() * max) + 1; // b 1 ~ 9int k = Math.min(a, b);int m = Math.max(a, b);// k < mif (k == m) {m++;}int[] arr = randomArray(kinds, range, k, m);int ans1 = test(arr, k, m);int ans2 = onlyKTimes(arr, k, m);if (ans1 != ans2) {System.out.println(ans1);System.out.println(ans2);System.out.println("出错了!");}}System.out.println("测试结束");}}

异或运算和几个经典题目解析相关推荐

  1. 计算机网络知识副标题,计算机统考常见题解答及经典题型解析.doc

    计算机统考常见题解答及经典题型解析 计算机统考常见问题解答 1.哪些学生需要参加统考? 答:教育部批准的试点高校和中央电大"人才培养模式改革和开放教育试点"项目中自2004年3月1 ...

  2. 异或运算的基本介绍以及使用技巧,剖析常见的异或题目

    关于异或运算 一.异或运算的基本介绍 二.异或运算的性质 三.异或运算的经典题目 1.题目1 2.题目2 3.题目3 4.题目4 5.题目5 四.异或运算小结 一.异或运算的基本介绍 异或运算,符号为 ...

  3. 经典算法之异或运算(无进位相加)

    目录 异或运算的定义 异或运算的性质 异或运算的应用 交换两数 翻转指定位 寻找单身狗 异或运算的定义 众所周知,计算机中的所有数据都是以二进制(0或者1)的形式存储.而异或运算符(^)就是将参加运算 ...

  4. 你管这玩意叫异或运算?

    对于底层开发来说,位运算是非常重要的一类操作.而对于位运算来说,最有意思的,应该就是异或运算(XOR)了. 提到异或运算,很多同学可能首先想到的就是一个经典的,和异或运算相关的面试问题: 给你一个包含 ...

  5. 史上最通俗易懂的异或运算详解【含例题及应用】

    一. 什么是异或? 1. Wikipedia的解释: 在逻辑学中,逻辑算符异或(exclusive or)是对两个运算元的一种逻辑析取类型,符号为 XOR 或 EOR 或 ⊕(编程语言中常用^).但与 ...

  6. 异或运算练习:找出一组数中唯一(唯二)出现奇数次的数

    题目描述 已知一个数组,现在请你用时间复杂度O(n),空间复杂度O(1)的算法求解: 1.假设数组中只有一个数的数量为奇数,其余都是偶数,请求出这个数. 2.假设数组中有两个数的数量为奇数,其余都是偶 ...

  7. 十个利用矩阵乘法解决的经典题目

    出自matrix67.com 好像目前还没有这方面题目的总结.这几天连续看到四个问这类题目的人,今天在这里简单写一下.这里我们不介绍其它有关矩阵的知识,只介绍矩阵乘法和相关性质.     不要以为数学 ...

  8. FEC之异或运算应用

    话说为啥FEC需要异或( ^/⊕ )操作呢? 异或:xor 异或运算规则: 0 xor 0 = 0 0 xor 1 = 1 1 xor 0 = 1 1 xor 1 = 0 异或运算特性: 1). a ...

  9. 异或运算_专题 | 异或运算的一些应用

    点击上方蓝字设为星标 每周一.三.五上午 8:30 准时推送 下面开始今天的学习- 定义 异或是一个数学运算,用于逻辑运算.如果 a.b 两个值不同,则异或结果为 1 ,否则结果为 0 .真值表如下: ...

最新文章

  1. python数字图像的行 宽的不同处 cv2.resize(1389,1500) p1列宽 p2 行高 stop2.shape 得(640,960,3) v1列宽 v2 行高 v3 通道数
  2. 参加第十六届智能车竞赛同学提问与回答-6-30
  3. 雅客EXCEL(6)-通用表格格式、销售实际案例(总结之前的知识点)
  4. 【堆叠抓取+深度学习】基于深度学习+PPO深度强化学习的堆叠物体抓取算法的MATLAB仿真
  5. linux7 设置dns,RHEL7.0 系列-设置IP地址、网关和DNS
  6. 牛客题霸 [ 最长回文子串] C++题解/答案
  7. C语言基础教程读书笔记5.2.(第五章函数和存储类2)
  8. 运算阶乘的代码_【必修1】2.4可以复用的代码
  9. Android系统(122)---MTK 平台如何打开ActivityManagerService的debug开关
  10. JVM面试重点总结(一)——java内存区域与内存溢出异常
  11. 3.数据库操作相关术语,Oracle认证,insert into,批量插入,update tablename set,delete和truncate的差别,sql文件导入...
  12. c语言课程设计报告万年历,c语言课程设计报告-万年历系统.doc
  13. win10自带的打印机服务器,win10系统打印服务器安装设置的详细方法
  14. 用户调研---问卷调查
  15. python:相对路径的参照物会发生变化
  16. Ubuntu18.04之微信中文乱码解决(五十八)
  17. 精进之路-day01
  18. IOS取消“橡皮筋“效果
  19. 质量检验中那些不为人所知的事儿
  20. Android 仿今日头条频道管理(下)(GridView之间Item的移动和拖拽)

热门文章

  1. 明年将突破2000亿元大关,中国母婴行业处在哪个阶段?企业如何应对“危”与“机”?...
  2. 长文分享丨TI AM5718的PRU开发详解
  3. 足疗师手把手教你家中做足疗
  4. win7计算机安全配置文件,详述Win7安全模式下的多种功能 -电脑资料
  5. DCL——数据控制语言
  6. 汽车宣传软文怎么写?汽车促销写作技巧
  7. 近邻的距离度量表示法
  8. linux f中文版下载,Linux上的杀毒软件F-PROT及下载
  9. Hadoop学习(16)-MapReduce的shuffle详解
  10. 美国国家公园瀑布下现彩虹奇观