算法之异或
0 ^ N = 0 N ^ N = 0 1 ^ N = 1 (a ^ b) ^ c = a ^ (b ^ c) a ^ b = b ^ a
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] ;
}
2、一个数组中一个数出现了奇数次,剩下数都出现了偶数次,找到并打印
public static int findOdd ( int [ ] arr) {
int res = 0 ;
for ( int i = 0 ; i < arr. length; i++ ) {
res = res ^ arr[ i] ;
}
return res;
}
3、提取一个整形最右边的1
public static int find ( int num) {
return num & ( ~ num + 1 ) ;
}
4、一个数组中两种数字出现了奇数次,其余都出现了偶数次,找到并打印这个数
三次异或
总体异或一次 异或对应位为1的数,即可解出其中一个数 前两次答案异或,得出另一个数
public static int [ ] printOddTimesNum2 ( int [ ] arr) {
int eor = 0 ;
for ( int i = 0 ; i < arr. length; i ++ ) {
eor ^= arr[ i] ;
}
int rightOne = eor & ( ~ eor + 1 ) ;
int onlyOne = 0 ;
for ( int i = 0 ; i < arr. length; i++ ) {
if ( ( rightOne & arr[ i] ) != 0 ) {
onlyOne = arr[ i] ^ onlyOne;
}
}
eor = eor ^ onlyOne;
return new int [ ] { eor, onlyOne} ;
}
5、一个数组中有一个数出现k次,其他数出现了M次(K < M,M > 1,O(N))
一个数出现了K次,另一个数字出现了M次,且K<M,M > 1;并且时间复杂度为O(1) 可以改进一个数出现k次,一个数不出现k次,其余m次。可以在模m后再模k不为0得出 -> 不出现k次的元素
package class_01. xor ;
import javax. swing. * ;
import java. util. Arrays ;
import java. util. HashMap ;
import java. util. HashSet ;
public class Code_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 int onlyKTimes ( int [ ] arr, int k, int m) {
int [ ] t = new int [ 32 ] ;
for ( int i = 0 ; i < arr. length; i++ ) {
for ( int j = 0 ; j <= 31 ; j++ ) {
t[ j] += ( ( arr[ i] >> j) & 1 ) ;
}
}
int res = 0 ;
for ( int i = 0 ; i < 32 ; i++ ) {
if ( ( t[ i] % m) != 0 ) {
res |= ( 1 << i) ;
}
}
if ( res == 0 ) {
int count = 0 ;
for ( int num : arr) {
if ( num == 0 ) {
count++ ;
}
}
if ( count != k) {
return - 1 ;
}
}
return res;
}
public static int [ ] randArray ( int maxKinds, int range, int k, int m) {
int ktimeNum = ( int ) ( Math . random ( ) * maxKinds) + 1 ;
int numKinds = ( int ) ( Math . random ( ) * maxKinds) + 2 ;
int [ ] arr = new int [ k + ( numKinds - 1 ) * m] ;
int index = 0 ;
for ( ; index < k; index++ ) {
arr[ index] = ktimeNum;
}
numKinds-- ;
HashSet < Integer > set = new HashSet < > ( ) ;
set. add ( ktimeNum) ;
while ( numKinds != 0 ) {
int curNum = 0 ;
do {
curNum = ( int ) ( Math . random ( ) * range) + 1 ;
} while ( set. contains ( curNum) ) ;
set. add ( curNum) ;
numKinds-- ;
for ( int i = 0 ; i < m; i++ ) {
arr[ index++ ] = curNum;
}
}
for ( int i = 0 ; i < arr. length; i++ ) {
int j = ( int ) ( Math . random ( ) * arr. length) ;
int tmp = arr[ i] ;
arr[ i] = arr[ j] ;
arr[ j] = tmp;
}
return arr;
}
public static void main ( String [ ] args) {
int kinds = 4 ;
int range = 200 ;
int max = 9 ;
int testTimes = 100000 ;
System . out. println ( "测试开始..." ) ;
for ( int i = 0 ; i < testTimes; i++ ) {
int a = ( int ) ( Math . random ( ) * max ) + 1 ;
int b = ( int ) ( Math . random ( ) * max ) + 1 ;
int k = Math . min ( a, b) ;
int m = Math . max ( a, b) ;
if ( k == m) {
m++ ;
}
int [ ] arr = randArray ( kinds, range, k, m) ;
int ans1 = test ( arr, k, m) ;
int ans2 = onlyKTimes ( arr, k, m) ;
if ( ans1 != ans2) {
System . out. println ( "出错了....." ) ;
}
}
System . out. println ( "测试结束..." ) ;
}
}