LeetCode Java刷题笔记—137. 只出现一次的数字 II

137. 只出现一次的数字 II

给你一个整数数组 nums ,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。

中等难度。我们可以对每个二进制位单独计数,然后统计每个二进制位的1的计数值结果 %3的结果,如果结果是0,则表示只出现一次的元素的当前位为0;如果结果是1,则表示只出现一次的元素的当前位为1。

/**
 * 每个二进制位单独计数,然后统计每个二进制位的1的数量 mod 3的结果
 */
public int singleNumber( int[] nums ){
   //result表述最终返回的出现一次的数
   int result = 0;
   //对每个数的每一位进行单独统计
   for( int i = 0; i < 32; i++ ){
      //每个数的对应位的和
      int sum = 0;
      //对每个数进行对应位的值进行求和
      for( int num : nums ){
         //当前数右移i位,并且和1进行&运算,获取当前数的第i位的二进制的值,并且相加
         sum += ( ( num >> i ) & 1 );
      }
      //用和对3取模,获取对应位的运算结果,如果是0表示出现一次的数对应位是0,如果是1表示对应位是1
      //然后将运算结果左移i位,再与最终值进行与运算,这样就能让最终值对应位的值变成当前计算的结果值
      result |= ( ( sum % 3 ) << i );
   }
   //返回最终结果
   return result;
}

上面这种解法的好处是,此后对于出现了k个一样的数的题目,那么我们使用%k即可求解。

另一种更难理解的方法,使用纯粹的位运算,我们使用两个数,这两个数的对应位来记录最终返回的数的对应位的值的情况。

public int singleNumber( int[] nums ){

   int one = 0, two = 0;
   for( int num : nums ){
      one = one ^ num & ~two;
      two = two ^ num & ~one;
   }
   return one;
}

刚开始时,在第i位,a和b的对应位二进制值都是0。

在第i位如果第1次遇到1,则a对应位二进制值为1,a对应位二进制为0。

在第i位如果第2次遇到1,则a对应位二进制值为0,a对应位二进制为1。

在第i位如果第3次遇到1,则a对应位二进制值为0,a对应位二进制为0,回到原点。

后续的计算以此类推,我们发现,该位最终运算结束后的值就是只出现一次的元素对应位的值。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刘Java

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值