位运算(上)

菜鸟日记—1月18日

案例1:

数组中确定唯一成对的数

1~N-1在长度为N的数组中,只有唯一一个元素值重复,其它均只出现一次
每个数组元素只能访问一次,设计一个算法将他找出来,不用辅助空间

*第一种方法
构造新数组与其进行与运算

先构造数组

public class 数组中确定唯一成对的数 {
    
    
    public static void main(String[] args) {
    
    
    int N = 11;		//N可自己自行设置
    int[] arr = new int[N];
    for (int i = 0; i < arr.length-1; i++) {
    
    
        arr[i] = i + 1;}

最后一个数取随机数,并与前面随机一个元素对换位置

	//最后一个数取随机数
    arr[arr.length-1] = new Random().nextInt(N-1)+1;
    //随机下标
    int index = new Random().nextInt(N);
    //最后一个数与前面随机一个数互换位置
    int t=arr[N-1];
    arr[N-1]=arr[index];
    arr[index]=t;
    System.out.println(Arrays.toString(arr));
    int x = 0;

构造新数组与其进行与运算并输出

	//构造一个1~N-1的数组
    for (int i = 0; i < N-1; i++) {
    
    
        x = x ^ (i + 1);
        }
    //新数组与旧数组作亦或运算,其余相同的数亦或为零
    //而成对的数加新数组里面那个数则有3个,所以亦或结果便是成对的那个数
    for (int i = 0; i < N; i++) {
    
    
        x ^= arr[i];
        }
    System.out.println(x);

*第二种方法

辅助空间解法(暴力破解)

int[] f = new int[N];
        for (int i = 0; i <N ; i++) {
    
    
            f[arr[i]] += 1;//原先每个元素都是0,现在给下标为arr[i]的每个都加1
                            //因为其中有两个数是一样的,所以会加两次
        }
        //System.out.println(Arrays.toString(f));
        for (int i = 0; i < N; i++) {
    
    
            //当新数组中某个元素等于2时,那么他的下标就是重复的那个数
            // (因为第一个元素被0占用了,所以下标不用加一)
            if(f[i]==2){
    
    
                System.out.println(i);
            }
        }
    }
}

效果图:

每次结果都不一样
在这里插入图片描述
在这里插入图片描述

案例2:

求二进制中’1’的个数

输一个整数,判断其二进制中有多少个’1’

有三种解法

1.从右往左依次比对

public class 二进制中1的个数 {
    
    
    public static void main(String[] args) {
    
    
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        System.out.println(Integer.toString(N,2));
        //1.从右往左挨个比对是否为1
        int count1 = 0;
        for (int i = 0; i < 32; i++) {
    
    
            if ((N&(1<<i))==(1<<i)){
    
    
                count1++;
            }
        }
        System.out.println(count1);

2.从左往右依次比对

	int count2 = 0;
        for (int i = 0; i < 32; i++) {
    
    
            if (((N>>i)&1)==1){
    
    
                count2++;
            }
        }
        System.out.println(count2);

3.减1法
通过将输入的数减1与原数进行与运算,与几次就有几个1

	int count3 = 0;
        //因为不知道要循环几次,所以用while
        while (N != 0){
    
    
            N = (N-1)&N;
            count3++;
        }
        System.out.println(count3);
    }
}

下面是减1法的图解,些许潦草,别介意
假设输入的数是20,有两个1,则与两次
在这里插入图片描述
效果图:
在这里插入图片描述

案例3:

是不是2的整次方

输入一个数,判断其是不是2的整数次方
思考:当一个数的二进制位上有且只有一个1时,那么他便是2的整数次方;
比如:8只有从右往左第4位为一,64则是第7位

public class 是不是2的整次方 {
    
    
    public static void main(String[] args) {
    
    
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        int a = 2;
        if ((N & (N - 1)) == 0){
    
    
            System.out.println("yes");
        }
        else {
    
    
            System.out.println("no");
        }
    }
}

效果图:
在这里插入图片描述
在这里插入图片描述
案例4:

奇偶位互换

给出一个整数,将他的二进制奇偶位互换,并验证互换是否成功
如9的二进制为: 1001,奇偶位互换后为:0110等于6

public class 交换奇偶位 {
    
    
    public static void main(String[] args) {
    
    
        int a = 9;
        int b = huan(a);
        //验证换位是否成功,9奇偶位互换等于6
        int c = 6;
        System.out.println(b);
        if (c == b){
    
    
            System.out.println("yes");
        }
    }

    private static int huan(int i) {
    
    
    	//这里用二进制太长了,我用十六进制表示
        int ji = i & 0x55555555; //和1010 1010 1010 1010......做与运算取出奇数位
        int ou = i & 0xaaaaaaaa; //和0101 0101 0101 0101......做与运算取出偶数位
        return (ji << 1) ^ (ou >> 1); //合并成一个二进制数
    }
}

图解:
假设要互换的数是9
在这里插入图片描述
效果图:
在这里插入图片描述

over!!!
寒冷而充实的一天结束。

猜你喜欢

转载自blog.csdn.net/ghl971/article/details/112786217