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

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));
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值