异或概念:相同为0,不同为1.(又叫无进位相加),和出现的位序没有关系。
不同额外变量交换两个数(a和b必须是不同位置)
a=a^b b=a^b a=a^b
题目二:一个数组中有一种数出现了奇数次,其他数都出现了偶数次,怎么找到并打印这个数。
eor=eor^a^b^c^d....
题目三:怎么把一个int类型的数,提取出最右侧的1来。
a&(-a)
&:两边同时为1才是1,否则就是0。
(~a+1)=-a(取反加1等于自己的相反数)
题目四:一个数组中有两种数出现了奇数次,其他数都出现了偶数次,怎么找到并打印这两种数。
思想:
假设数组中a和b出现了奇数次。
用变量eor把所有的变量都异或一次,结果就是a^b。
把a^b结果中最右侧的1提取出来,假设这一位为N,说明a,和b在第n位上的字母不一样。
把原来的数分为两类,第一类是第n位上是1的数,第二类是第n位上不是1的数。
这样用eor’来得出第一类异或的结果,结果就是a或b.然后eor^eor’这样就得出了另一个数。
eor =a^b(所有数都异或了一次)
public class Code04_print { //arr中有两种数出现奇数次 public static void printOddTimesNum2(int []arr){ int eor=0; for(int i=0;i<arr.length;i++){ eor^=arr[i];//得出的结果为a^b } //将最右侧的1提取出来 int rightOne=eor&(-eor);//0001000 int onlyOne=0;//eor' for(int i=0;i<arr.length;i++){ if((arr[i]&rightOne)!=0){//arr[i]只有最后一位等于1的时候,结果才不等于0 onlyOne^=arr[i]; } } System.out.println("a="+onlyOne+"b="+(onlyOne^eor));//a和b分别的两个数 } public static void main(String[] args) { int arr[]={1,2,3,1,1,1,5,5,6,6}; printOddTimesNum2(arr); } }
题目五:一个数组中有一种数出现K次,其他数都出现了M次,M>1,K<M;找到,出现了K次的数,要求,额外空间复杂度O(1),时间复杂度O(N)
将数组中的数字转换成二进制,然后累加。看每个位上的能否被m整除,如果能被m整除,则这个数字在这一位上的数为0,如果不能被M整除,则这个数字在这一位上的数为1。