其他分享
首页 > 其他分享> > 面试题收集(持续更新~)

面试题收集(持续更新~)

作者:互联网

1、关于位运算的使用

(题目一)、在一个数组中,有一个数出现了奇数次,其他数都出现了偶数次,请问怎么知道出现奇数次的数是什么,要求时间复杂度是O( N ) ,空间复杂度是 O( 1 )。

(题目二)、在一个数组中,有两个数出现了奇数次,其他数都出现了偶数次,请问怎么知道出现奇数次的两个数分别是什么,要求时间复杂度是O( N ) ,空间复杂度是 O( 1 )。

提示:异或运算,异或运算支持 交换律、结合律


题目一解答:创建一个成员变量eor为 0 ,将数组遍历一次,每个元素都与成员变量进行异或运算,出现偶数次的数都会被消除,所以最后成员变量的值就是出现奇数次的那个数了;

题目二解答:首先还是创建一个成员变量eor1为0,将数组遍历一次,每个元素都与成员变量进行异或运算,出现偶数次的数都会被消除,所以最后成员变量的值就是出现奇数次的那两个数的异或值了,eor1为两个数的异或值。因为两个数不相等,所以异或结果一定不为0;从二进制的角度看就是这两个数的二进制数至少有一位是不相同的,这就是这道题的突破口。我们可以再创建一个成员变量eor1为0,找出所以那一位是 0 或者 1 的数,再和成员变量eor2进行异或,那么得到的结果一定是这两个数中的其中一个,最后拿这个数与eor1进行异或运算就可以得到另外一个数了;

以下是这两道题的代码:

public class EvenTimeAddTime {

    public static void main(String[] args) {
        int[] arr1 = {3, 3, 5, 5, 2, 2, 2, 2, 7, 1, 1};
        int [] arr2 = new int[]{3,3,5,5,5,2,2,2,2,7,1,1};
        process1(arr1);
        process2(arr2);
    }

    //题目一
    public static void process1(int[] arr) {
        int eor = 0;
        for (int i : arr) {
            eor ^= i;
        }
        System.out.println("---------题目一----------");
        System.out.println(eor);
    }

    //题目二
    public static void process2(int[] arr) {
        int eor1 = 0;
        for (int i : arr) {
            //两个出现奇数次的元素的异或值
            eor1 ^= i;
        }
        //提取出eor1二进制中最右边的1
        int rightOne = eor1 & (~eor1 + 1);
        int eor2 = 0;
        for (int j : arr) {
            //筛选出与rightOne二进制为1对应位不同的数进行异或,就可以得到一个奇数次的数了
            if ((rightOne & j) == 0) {
                eor2 ^= j;
            }
        }
        System.out.println("---------题目二----------");
        System.out.println("一个出现奇数次的数:" + eor2);
        System.out.println("另一个出现奇数次的数:" + (eor2 ^ eor1));
    }
}

标签:eor2,面试题,eor1,题目,收集,int,更新,异或,数次
来源: https://blog.csdn.net/qq_45331617/article/details/120586639