异或运算的相关算法:找到数组中出现奇数次的数

【题目】

给一个数组arr,其中只有一个数出现了奇数次,其它数出现了偶数次,打印这个数。

【输入】

 输出包含两行,第一行包含一个整数n(1 \leq n \leq 10^5)(1≤n≤105),代表数组arr长度,第二行有n个数,代表数组arrarr_i 为32位整数arri​为32位整数。输出包含两行,第一行包含一个整数n(1 \leq n \leq 10^5)(1≤n≤105),代表数组arr长度,第二行有n个数,代表数组arrarr_i 为32位整数arri​为32位整数。

【输出】

输出一个整数,代表出现次数为奇数次的那个数。

【示例】

输入:5

           3 1 3 1 2

输出:2

【复杂度】

时间复杂度O(n),额外空间复杂度O(1)。

【代码】

import java.util.*;
public class Main {
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int count = sc.nextInt();
        int res = 0;
        //每次将输入的值进行异或运算
        for(int i=0;i<count;i++){
            int tmp = sc.nextInt();
            res ^= tmp;
        }
        System.out.println(res);
    }
}

进阶:数组中存在两个出现奇数次的数

【题目】

给定一个数字arr,其中只有两个数字出现了奇数次,其它数字都出现了偶数次,按照从小到大顺序输出这两个数。 

 【输入】

第一行输入一个n,第二行输入n个数

【输出】

输出出现奇数次的两个数,按照从小到大的顺序。 

【示例】

输入 4

         1 1 2 3
输出
        2 3

【分析】

  1. 先把数组中所有数全部异或运算,得到的结果为两个所求数ab的异或值

  2. 由于ab异或的值不为0(因为如果为0,那么意味着ab相等),所以ab的二进制位中必然存在一个不相等的位,对ab两个数进行异或运算时,这个位上的运算结果为1,所以要先找到ab异或结果中为1的位置(找到一位即可),那么我们找最右侧的1

    寻找的方法是:把ab异或后的结果eor取反后加1,然后与eor进行并运算(rightOne的结果如:(00000100)

    int rightOne = eor & (~eor +1);
  3. 筛选出所有在该位置上不为1的数进行异或运算(这样做的目的是把a和b分开,进行异或运算得到其中一个数)

    if((cur & rightOne) == 0)             //筛选出所有在该位置上不为1的数进行异或
    if((cur & rightOne) == rightOne)      //筛选出所有在该位置上为1的数进行异或
  4. 这样,有了a和b的异或值,有了a或b的值,那么将eor和neweor异或就能得到另一个值

【代码】

import java.util.*;
public class Main {
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int count = sc.nextInt();
        int[] arr = new int[count];
        int total = 0;
        //求出总体的异或和
        for(int i=0; i<count; i++){
            arr[i] = sc.nextInt();
            total ^= arr[i];
        }
        //取出异或和的最右侧的‘1’位
        total = total & (~total + 1);
        int even = 0;
        int odd = 0;
        for(int i=0; i<count; i++){
            //‘1’位上为0的数进行异或和
            if((arr[i]&total) == 0){
                even ^= arr[i];
            }
            //‘1’位上位1的数异或求和
            else{
                odd ^= arr[i];
            }
        }
        int[] res = new int[2];
        res[0] = even<odd?even:odd;
        res[1] = even+odd-res[0];
        System.out.println(res[0]+" "+res[1]);
    } 
}

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值