位运算的之美(合集)

题目一

一个数组里除了某-一个数字之外,其他的数字都出现了两次。请写程序找出这个只出现一次的数字。

暴力思路:使用Map记录数字出现的数量,最后找出出现一次的。

巧妙思路:使用异或符号(^),异或符号为不进位加法,两个相同的数字异或为0,所以可以利用这个性质将所有数字异或一遍,最终的就是答案答案。

	public static void main(String[] args) {
        int nums[] = {1,1,2,2,3,4,5,3,4};
        System.out.println(Arrays.toString(nums));
        int res = 0;
        for (int i = 0; i <nums.length ; i++) {
            res = res^nums[i];
        }
        System.out.println(res);
    }

题目二

1- 1000这1000个数放在含有1001个元素的数组中,只有唯一的一一个元素值重复,其它均只出现一次。每个数组元素只能访问一次,设计一个算法,将它找出来;不用辅助存储空间,能否设计一个算法实现?

暴力思路:使用Map记录数字出现的数量,最后找出出现两次的。

巧妙思路:和第一题类似,使用异或符号(^),异或符号为不进位加法,两个相同的数字异或为0,所以可以利用这个性质来寻求答案。

    public static void main(String[] args) {
        int size = 5;
        int nums[] = new int[size+1];
        for(int i=0;i<size;i++){
            nums[i]=i+1;
        }
        nums[size]=(int)(Math.random()*size);
        System.out.println(Arrays.toString(nums));
        int tmp = 0;
        // 先对 tmp 从 1-size 做一下异或操作
        for (int i = 1; i <= size; i++) {
            tmp = tmp^i;
        }
        // 在对每一个数进行异或,相同的数字将变为,最终剩下的数字为答案
        for (int i = 0; i <= size ; i++) {
            tmp = tmp^nums[i];
        }
        System.out.println(tmp);
    }

题目三

请实现一个函数,输入一个整数,输出该数二进制表示中1的个数。
例: 9的二进制表示为1001,有2位是1

暴力思路:将数字转换为二进制,通过遍历的方式统计1的数量。

	public static void main(String[] args) {
        int n = 9;
        String s = Integer.toBinaryString(n);
        System.out.println(s);
        char[] chars = s.toCharArray();
        int count=0;
        for (int i = 0; i < chars.length; i++) {
            if(chars[i]=='1'){
                count++;
            }
        }
        System.out.println(count);
    }

巧妙思路:可以借助左移(<<)符号来快速统计,左移每次移动一次二进制数,末尾补0,如果 int 类型数据可以通过移动 32 次来获取答案。

    public static void main(String[] args) {
        int n = 9;
        String s = Integer.toBinaryString(n);
        System.out.println(s);
        int count = 0;
        for (int i = 1; i <= 32 ; i++) {
            if((n&(1<<i)) == (1<<i)){
                count++;
            }
        }
        System.out.println(count);
    }

题目四

判断一个数是不是 2 的整数次方

暴力思路:每次除2,判断位数是否是整数。

巧妙思路:将一个数与这个数减一进行与运算,判断得到的结果是否为0既可知道其是否为整数。
例如:8(1000)^7(0111)=0

	public static void main(String[] args) {
        int n1 = 8;
        int n2 = 9;
        System.out.println((n1&(n1-1))==0);
        System.out.println((n2&(n2-1))==0);
    }

题目五

将整数的二进制奇偶位进行交换

暴力思路:将数字转换为二进制,然后做两两交换操作。

巧妙思路:将原数字与(010101…01)进行与运算,得到a;在将原数组与(1010…10)进行与运算,得到b;然后将a左移一位和b右移一位进行异或操作,最终得到的数字就为结果了。

    public static void main(String[] args) {
        int n = 6;
        int a = n&0x55555555;//0101....01
        int b = n&0xaaaaaaaa;//1010....10
        System.out.println((a<<1)^(b>>1));
    }
发布了39 篇原创文章 · 获赞 20 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/cong____cong/article/details/104240916