【数据结构与算法】03(java)二分查找、异或运算

二分查找
在已有序的序列中按值,与数组mid位置的数比较

package com.algorithm;

public class BSExist {

    public static void main(String[] args) {
        int[] arr = {1, 2, 3, 4, 5, 5, 6, 7, 8, 8, 9};
        boolean isExist = exist(arr,10);
        System.out.println(isExist);
    }

    public static boolean exist(int[] sortedArr, int num) {
        if (sortedArr == null || sortedArr.length == 0) {
            return false;
        }

        int left = 0;
        int right = sortedArr.length - 1;
        int mid = 0;

        while (left < right) {
            mid = left + ((right - left) >> 1);//mid=(left+right)/2,位运算N*2+1可以写成(N<<1)|1左移一位再或1
            if (sortedArr[mid] == num) {
                return true;
            } else if (sortedArr[mid] > num) {
                right = mid - 1;//去mid左边找
            } else {
                left = mid + 1;//去右边查找
            }
        }
        return sortedArr[mid] == num;
    }
}

异或运算
相同为0,相异为1.(位运算时,简记为无进位的相加,偶数个1为0,奇数个1为1)
1、swap方法的异或写法

//交换的异或写法(前提i不等于j,内存空间不同)
    static void swap(int[] arr, int i, int j) {//a=甲,b=乙
        arr[i] = arr[i] ^ arr[j];//a=甲^乙,b=乙
        arr[j] = arr[i] ^ arr[j];//a=甲^乙,b=甲^乙^乙=甲
        arr[i] = arr[i] ^ arr[j];//a=甲^乙^甲=乙,b=甲
    }

2、一个数组中有一种数出现了奇数次,其他数都出现了偶数次,怎么找到并打印这种数

//arr中,只有一种数,出现奇数次
    public static void printOddTimeNum1(int[] arr) {
        int eor = 0;//0与任何数异或,为原来的数
        for (int i = 0; i < arr.length; i++) {
            eor ^= arr[i];
        }
        System.out.print(eor);
    }

3、提取int整型的数的最右侧的1
N&(~N+1),既N与(N取反+1)

//数出int数中二进制1的个数
    public static int bitCounts(int N) {
        int count = 0;

        //011011010000
        //000000010000 rightOne
        //011011000000 循环1次后
        while (N != 0) {
            int rightOne = N & ((~N) + 1);//提取出最右侧的1
            count++;
            N ^= rightOne;//抹掉最右侧的1
        }
        return count;
    }

4、一个数组中有两种数出现了奇数次,其他数都出现了偶数次,怎么找到并打印这两种数

package com.algorithm;

public class EvenTimeOddTime {
    public static void main(String[] args) {
        int[] arr = {1, 1, 2, 2, 3, 3, 3, 4, 4, 4};
        //printOddTimeNum1(arr);
        printOddTimesNum2(arr);
    }

    //一个数组中有一种数出现了奇数次,其他数都出现了偶数次,怎么找到并打印这种数
    //arr中,只有一种数,出现奇数次
    public static void printOddTimeNum1(int[] arr) {
        int eor = 0;//0与任何数异或,为原来的数
        for (int i = 0; i < arr.length; i++) {
            eor ^= arr[i];
        }
        System.out.print(eor);
    }

    //提取int整型的数的最右侧的1
    //N&(~N+1)N与(N取反+1)
    //一个数组中有两种数出现了奇数次,其他数都出现了偶数次,怎么找到并打印这两种数
    //异或运算遍历数组,最后eor=a异或b,eor不等于0,说明a和b在(a异或b)的右侧的一个1上,一个为1,一个为0,
    public static void printOddTimesNum2(int[] arr) {
        int eor = 0;
        for (int i = 0; i < arr.length; i++) {
            eor ^= arr[i];
        }

        //eor^=a^b
        //eor!=0,eor必然有一个位置上时1
        int rightOne = eor & (~eor + 1);//提取出最右的1,
        // eor=      01100100
        //rightOne = 00000100

        int onlyOne = 0;//eor`,提取出最右侧1和(a异或b)最右侧也是1的那个数
        for (int i = 0; i < arr.length; i++) {
            if ((arr[i] & rightOne) != 0) {//只有在00000100上有1的那些数字异或到onlyOne中
                onlyOne ^= arr[i];
            }
        }
        System.out.println(onlyOne + " " + (eor ^ onlyOne));
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值