数组中只出现一次的数
问题一:在一个整数数组中,除了一个数之外,其他的数出现的次数都是两次,求出现一次的数,要求时间复杂度尽可能的小。例如数组{1,2,2,3,3,6,6},出现一次的数是1.
从题目的描述可以看出,数组中只有一个数字出现了一次,其他的数字都出现两次,联想到异或运算的特点:任何一个数字和自己做异或运算的结果都是0,任何数字和0运算的结果都是本身。根据上述特点,可以考虑从数组的第一个元素开始,逐个和后面的元素做异或操作,最后的计算结果就是要找的只出现一次的数。
算法实现如下:
public class Main { public static void main(String[] args){ int[] nums = new int[]{1,2,2,3,3,4,4,1,23}; System.out.println(getNumAppearsOnce(nums)); } public static int getNumAppearsOnce(int[] nums){ if(nums == null || nums.length <= 2){ throw new IllegalArgumentException("nums size must bigger than 2"); } int result = 0; for(int i=0;i<nums.length;i++){ result ^= nums[i]; } return result; } }
由于只需要遍历一遍数组就可以找到结果,因此上述算法的时间复杂度为O(N),其中N为数组的长度
发散思维:假如要求的数组里面有两个数出现的次数是1,其他出现的次数都是2,如何找出这两个数呢?
根据上面问题一的思路,我们依然从头到位对数组做异或运算,得到的最终结果应该是两个不同数字做异或运算后的值。因为两个数字不相同,最终的结果也肯定不是0,切结果对应的二进制位中至少有一个为1,我们找到二进制位中第一个是1的位置,即为n,然后根据地n为是1还是0把数组分为两个子数组,第一个子数组中的每个数的二进制位的第n位都是1,另外一个是0,这样分完后,相同的数字肯定会被分到同一个子数组中,并且每个子数组中只包含一个只出现一次的数,根据问题一,我们可以很方便的求出两个只出现一次的数,实现如下:
public class Main { public static void main(String[] args){ int[] nums = new int[]{1,2,2,3,3,4,4,1,23,43}; System.out.println(getNumsAppearsOnce(nums)); } public static int getNumAppearsOnce(int[] nums){ if(nums == null || nums.length <= 2){ throw new IllegalArgumentException("nums size must bigger than 2"); } int result = 0; for(int i=0;i<nums.length;i++){ result ^= nums[i]; } return result; } public static List<Integer> getNumsAppearsOnce(int[] nums){ if(nums == null || nums.length <= 2){ throw new IllegalArgumentException("nums size must bigger than 2"); } List<Integer> result = new ArrayList<Integer>(2); int temp = getNumAppearsOnce(nums); int index = findFirstBitIdOne(temp); int num1 = 0,num2 = 0; for(int i=0;i<nums.length;i++){ if(isBitOne(nums[i],index)){ num1 ^= nums[i]; }else{ num2 ^= nums[i]; } } result.add(num1); result.add(num2); return result; } private static boolean isBitOne(int num, int index) { num = num >> index; return (num & 1) == 1; } private static int findFirstBitIdOne(int temp) { int index = 0; while((temp & 1) == 0){ temp = temp >> 1; index++; } return index; } }
每天进步一点点