记录方法。使用位运算。
先对所有数字进行一次异或,得到两个出现一次的数字的异或值。
在异或结果中找到为1的最低一位的位置。(这个二进制数中是1的二进制位暗含了什么个意思呢?分析不难知道,二进制位是1,就表示这两个数字在这个二进制位上的数是不同的。所以,这就是我们划分两个数到不同组的依据。)
根据这一位对所有的数字进行分组。
在每个组内进行异或操作,得到两个数字。
import java.util.*; public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param array int整型一维数组 * @return int整型一维数组 */ public int[] FindNumsAppearOnce (int[] nums) { //xor用来计算nums的异或和 int xor = 0; // 计算异或和 并存到xor // e.g. [2,4,2,3,3,6] 异或和:(2^2)^(3^3)^(4^6)=2=010 for(int num : nums) xor ^= num; //设置mask为1,则二进制为0001 // mask是一个二进制数,且其中只有一位是1,其他位全是0,比如000010, // 表示我们用倒数第二位作为分组标准,倒数第二位是0的数字分到一组,倒数第二位是1的分到另一组 int mask = 1; // & operator只有1&1时等于1 其余等于0 // 用上面的e.g. 4和6的二进制是不同的 我们从右到左找到第一个不同的位就可以分组 4=0100 6=0110 // 根据e.g. 010 & 001 = 000 = 0则 mask=010 // 010 & 010 != 0 所以mask=010 // 之后就可以用mask来将数组里的两个数分区分开 //找到xor中第几位是1 while((xor & mask)==0){ mask <<= 1; //左移一位 } //两个只出现一次的数字 int a=0, b=0; for(int num : nums){ //根据&是否为0区分将两个数字分区,并分别求异或和 if((num & mask)==0) {//第一组 a ^= num; } else{//第二组 b ^= num; } } return new int[]{a < b?a : b, a > b ? a:b}; } }