Java 实现数组中只出现一次的数字

一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。

代码

解法一

比较笨,先排序,是的相同的数字挨在一起,这样不同的数字必然和前后数字都不一致,对于数组的第一个和最后一个元素,则需要单独处理。

    public static List<Integer> findSignleAppearNumber(int[] array) {
        if (array == null || array.length <= 1) {
            return null;
        }
        // 如果数组的长度是奇数,不可能出现两个只出现一次的数字
        if (array.length % 2 == 1) {
            return null;
        }
        List<Integer> result = new ArrayList<>(2);
        if (array.length == 2) {
            for (int i : array) {
                result.add(i);
            }
            return result;
        }
        // 对数组排序,使得出现两次的数字可以挨着
        Arrays.sort(array);
        // 根据前面的判断条件,此时数组长度大于等于4
        // 如果第一个数字和第二个数字不相等,说明第一个数字就是只出现一次的数字
        if (array[0] != array[1]) {
            result.add(array[0]);
        }
        // 为了和前后数字对比,第一个数字和最后一个数字不比较
        for (int i = 1; i < array.length - 1; i++) {
            // 如果一个数字和其前后两个数字都不相等,说明该数字只出现一次
            if (array[i] != array[i - 1] && array[i] != array[i + 1]) {
                result.add(array[i]);
            }
        }
        // 如果遍历没有找到,说明数组的最后一个数字是要找的
        if (result.size() < 2) {
            result.add(array[array.length - 1]);
        }
        return result;
    }


    public static void main(String[] args) {
        int[] array = {1, 2, 2, 3};
        List<Integer> list = findSignleAppearNumber(array);
        for (Integer i : list) {
            System.out.println(i);
        }
    }

解法二

借助异或,任何一个数字异或它自己都等于0,只有都为0或者都为1,才为1,如果不相同则为0

    public static List<Integer> findSignleAppearNumber2(int[] array) {
        if (array == null || array.length <= 1) {
            return null;
        }
        // 如果数组的长度是奇数,不可能出现两个只出现一次的数字
        if (array.length % 2 == 1) {
            return null;
        }
        List<Integer> result = new ArrayList<>(2);
        if (array.length == 2) {
            for (int i : array) {
                result.add(i);
            }
            return result;
        }
        // 任何一个数字异或它自己都等于0,所以xor的结果是两个只出现一次的数字的异或结果
        int xor = 0;
        for (int i = 0; i < array.length; i++) {
            xor ^= array[i];
        }
        // 找出这个异或结果二进制第一次位为1的位置
        // 以此来将原数组切割为两个子数组,每个子数组包含一个只出现一次的数字
        // 因为位为1,说明两个数字在该位上不相同,即必然一个在该位上是0,另一个是1,这是异或的规则所致
        // 所以以此来划分数组,两个数字必然在不同子数组之中
        int bitIndex = findFirstBitIs1(xor);
        int n1 = 0;
        int n2 = 0;
        for (int i = 0; i < array.length; i++) {
            if (is1OfBitIndex(array[i], bitIndex)) {
                n1 ^= array[i];
            } else {
                n2 ^= array[i];
            }
        }
        result.add(n1);
        result.add(n2);
        return result;
    }

猜你喜欢

转载自blog.csdn.net/zl18310999566/article/details/80243413
今日推荐