day1--入门了解小测验

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表示这个数不存在。
    }
    

        
}

 

posted @ 2022-11-14 15:08  乐美  阅读(27)  评论(0)    收藏  举报