package day1;
import org.junit.Test;
public class WeiYunSuan {
@Test
public void test1(){
//抑或用于交换两个变量的值。
int num1=123;
int num2=321;
num1=num1^num2;
num2=num1^num2;//num1^num2^num2=num1;
num1=num1^num2;//num1^num2^num1=num2;
System.out.println("num1="+num1+",num2="+num2);
}
@Test
public void test2(){
//已知一个数组中,只有一个数是出现了奇数次,其他数都出现了偶数次,如何找到这个奇数
int[] arr=new int[]{12,12,13,13,14,14,54};
int ero=0;
/*
抑或运算的几点特征:
1.0^a=a;
2.a^a=0;
3.a^b^a=a^a^b=b;交换律
*/
for(int i=0;i<arr.length;i++){
ero^=arr[i];
}
System.out.println("唯一一个出现奇数次的数是:"+ero);
}
@Test
public void test3(){
//已知一个数组中,只有两个数是出现了奇数次,其他数都出现了偶数次,如何找到这两个奇数?
int[]arr=new int[]{12,13,12,14,15,14,16,17,17,16};//13和15出现了奇数次
int ero=0;
for(int i=0;i<arr.length;i++){
ero^=arr[i];//显然,循环结束后,得到ero=13^15;
}
int rightOne=ero&(~ero+1);//ero和它的取反加一做与运算,得到ero最右边为一的数.
//ero为1的那一位,是通过数组所有元素与0抑或得来,考虑到出现偶数次的元素互相抑或后为0;
//于是就只剩下只出现奇数次的数,出现奇数次的两个数抑或后在某一位取1,说明这两个数在这一位上一个取0一个取1;
int ero1=0;
for(int i=0;i<arr.length;i++){
//这两个数中只有一数满足该条件,通过这个条件判断,将满足条件的所有数和0做异或运算,就能求出这个满足条件的出现奇数次的数
if((arr[i]&rightOne)==rightOne)
ero1^=arr[i];//循环结束后,得到的ero1就是其中一个出现奇数次的元素
}
ero=ero^ero1;//求出第二个出现奇数次的数
System.out.println("这两个出现奇数次的值分别是:"+ero+","+ero1);
}
@Test
public void test4(){
//有序数组找某个数最左侧的数1 2 2 2 2 2 3 3 3 3 3 3 4 4 4 4 4 5 5 5 5 6 6 6 6 6 找num=3最左侧的位置;
int[] arr=new int[]{1,2,2,2,4,4,4,4,4,5,5,5,5,6,6,6,6,7,7,7,7,7,7,8,8};
/*方法1
int head=0;
int end=arr.length-1;
int num=3;
for(;;){
int middle=(head+end)/2;
if(arr[middle]>num){
end=middle-1;
}else if(arr[middle]<num){
head=middle+1;
}else{
for(int i=head;;i++){
if(arr[i]==num){
System.out.println(i);
break;
}
}break;
}*/
if(Search(arr,3)<0){
System.out.println("不存在这个数!");
}else{
System.out.println("这个数在数组中最左边的索引是:"+Search(arr,3));
}
}//方法2,封装成方法,且可以判断是否存在这个数
public int Search(int[] arr,int num){
int head=0;
int end=arr.length-1;
while(head<end){//二分法的大体结构,如果没有找到num也会也为条件设置的原因退出循环。
int middle=(head+end)/2;//每次比较后都要更新中值。
if(arr[middle]>num){
end=middle-1;
}else if(arr[middle]<num){
head=middle+1;
}else{
for(int i=head;;i++){
if(arr[i]==num){
return i;//找到最左边的就行,不再继续往下执行,之间返回索引。
}
}
}
}return -1;//如果程序没有从else出来(即没有找到这个数)则返回-1表示这个数不存在。
}
}