【知识积累】一个数组中有两个数出现了奇数次,其他数都出现了偶数次,怎么找到并打印这种数

package com.example.demo.algorithm;

/**
 * @Description :
 *
 * 一个数组中有两个数出现了奇数次,其他数都出现了偶数次,怎么找到并打印这种数
 * 所有的数异或一遍得到 eor = a^b
 * 既然a和b异或不等于0,那么a和b的某一位肯定不相同,要么a等于1,b等于0,要么a等于0,b等于1
 * 将数组中的数与这一个1不等于0,即array[i] & (eor & (~eor + 1)) != 0,就选出了所有这一位为1的数,这些数中要么包含a要么包含b
 * 那么将这些数异或就得到了a或者b,即eor1, 因为其他的数都是偶数,会被异或掉
 * 最后eor ^ eor1 = 另外一个数
 *
 * @Author : Darren
 * @Date : 2021 年 02 月 07 日 20:06:18
 * @since : 1.0
 */
public class J009_OddTimes {

    public static void main(String[] args) {
        int[] arrays2 = {4, 5, 5, 5, 4, 7, 6, 8, 6, 7, 7, 7};
        int[] eor1 = twoOddTimes(arrays2);
        J001_SelectSort.printArray(eor1);
    }

    public static int[] twoOddTimes(int[] arrays){
        if (arrays == null || arrays.length == 1){
            return arrays;
        }
        if (arrays.length == 2){
            return arrays;
        }
        //所有的数异或一遍得到 eor = a^b
        //既然a和b异或不等于0,那么a和b的某一位肯定不相同,要么a等于1,b等于0,要么a等于0,b等于1
        int eor = 0;
        for (int i = 0; i < arrays.length; i++) {
            eor ^= arrays[i];
        }

        int eor1 = 0;
        //提取二进制最右侧的1
        int rightOne = eor & (~eor + 1 );
        //找出所有数中这个位置为1的数,其中包含了出现奇数次的其中一个
        for (int i = 0; i < arrays.length; i++) {
            if ((arrays[i] & rightOne) != 0){
                //那么将这些数异或就得到了a或者b,即eor1, 因为其他的数都是偶数,会被异或掉
                eor1 ^= arrays[i];
            }
        }
        //a^b^? -> ?是a或者b 那么异或出来就剩下一个不相同的
        int eor2 = eor ^ eor1;
        return new int[]{eor1, eor2};
    }

}

 

Guess you like

Origin blog.csdn.net/axin1240101543/article/details/113758063