package class02;

/**
 * 1.在arr中,只有一种数字,出现了奇数次,其余的数都出现了偶数次。找出这个出现了奇数次的数字。
 * 2.在arr中,有两种数字,出现了奇数次,其余的数都出现了偶数次。找出这两种出现了奇数次的数字。
 */
public class Code02_EvenTimesOddTimes {
    public static void main(String[] args) {
        int[] arr = {1, 1, 2, 2, 3, 5, 5, 6, 6, 8, 8};//3出现了奇数次
        int[] arr2 = {1, 1, 2, 2, 6, 6, 6, 12, 12, 12};//6和12出现了出现了奇数次
        printOddTimesNum1(arr);
        printOddTimesNum2(arr2);
    }

    /**
     * 在arr中,只有一种数字,出现了奇数次,其余的数都出现了偶数次。找出这个出现了奇数次的数字。
     *
     * @param arr
     */
    private static void printOddTimesNum1(int[] arr) {
        int a = 0;
        for (int num : arr) {
            a ^= num;
        }
        System.out.println("a = " + a);
    }

    /**
     * 在arr中,有两种数字,出现了奇数次,其余的数都出现了偶数次。找出这两种出现了奇数次的数字。
     *
     * @param arr
     */
    private static void printOddTimesNum2(int[] arr) {
        int eor = 0;
        for (int i = 0; i < arr.length; i++) {
            eor ^= arr[i];
        }
        System.out.println("eor = " + eor);//eor:a^b

        int rightOne = eor & (-eor);//最右侧的1
        System.out.println("rightOne = " + rightOne);
        int onlyOne = 0;//eor'
        //算出rightOne后,我们就可以把arr中的所有的数,分成两类:
        //一类:rightOne为1的这一位,为1的数。
        //另一类:rightOne为1的这一位,为0的数。
        for (int i = 0; i < arr.length; i++) {
            //(arr[i] & rightOne) != 0,的意思是:
            //onlyOne要和arr数组中的谁进行异或操作呢?要和满足这个条件的数。
            //那么满足这个条件的数,都是什么数呢?
            //都是:对于arr[i],在rightOne为1的这一位,是1的数。因为如果不是1,即是0的话,&之后的结果就是0。
            if ((arr[i] & rightOne) != 0) {//关键代码,&后结果等于0,则说明arr[i]的这一位是0。&后结果不等于0,则说明arr[i]的这一位是1。
                onlyOne ^= arr[i];
            }
        }
        //走完循环后,此时onlyOne即eor',就是a或者是b。
        //也就是onlyOne抓到了,区域1中的,出现了奇数次的那个数,不是a就是b。
        //而eor是a^b,所以onlyOne ^ eor就是:a^(a^b),或者b^(a^b)。即a和b中另外一个。
        System.out.println(onlyOne);
        System.out.println(onlyOne ^ eor);
    }

    private static void printOddTimesNum3(int[] arr) {//只是去掉了注释
        int eor = 0;
        for (int i = 0; i < arr.length; i++) {
            eor ^= arr[i];
        }
        System.out.println("eor = " + eor);//eor:a^b
        int rightOne = eor & (-eor);//最右侧的1
        System.out.println("rightOne = " + rightOne);
        int onlyOne = 0;//eor'
        for (int i = 0; i < arr.length; i++) {
            if ((arr[i] & rightOne) != 0) {
                onlyOne ^= arr[i];
            }
        }
        System.out.println(onlyOne + ", " + (onlyOne ^ eor));
    }


}

 

原文地址:http://www.cnblogs.com/TheFloorIsNotTooHot/p/16838672.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性