原题地址
https://leetcode.com/problems/single-number-ii/

题目描述
Given an array of integers, every element appears three times except for one. Find that single one.
给出一个整数数组,除了某个元素外所有元素都出现三次。找出仅出现一次的数字。

Note:
注意:

Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?
你的算法需要在线性时间复杂度内运行。你可以在常数空间复杂度内实现吗?要求:时间复杂度O(n),空间复杂度O(1)。

Tags Bit Manipulation

解题思路
Single Number系列的第二题,第一题请看 Leetcode 136 Single Number 仅出现一次的数字 。

实际上136题是137题都是一个特例,更抽象的题目是,有一个数组,其中有一个元素出现了x次,其余所有元素都出现了y次(x < y),找出这个出现了x次的元素。关于这个问题,我们在另一篇文章里进行讨论(请看Leetcode Single Number 扩展)。这里我们只讨论137这个题目。

由于除去目标元素target之外,所有元素都出现3次,假设出现3次的元素有n个,这样的话假如我们统计所有元素的某一位(比如最后一位),其一共有3n+1个二进制位。因为对与同一个元素来说,其所有的二进制位一定是相同的,所以对这些元素的某一位来说一定是以3个1或3个0为单位出现的,即3n+1个二进制位中一定是3x个1和3y个0,其中x+y=n,再外加一个target对应的二进制位(1或0都有可能)。综上所述,我们可以统计所有数字每一位上1的个数,对3取模,如果为1就说明target对应位为1,否则为0。

下面问题就是如何统计每一位上1的个数,一个比较好的方法就是采用位运算来处理,当个数满3时就清零(当然这是参考的网上大神们的思路)。

我们用三个整数one,two, three的二进制位来分别表示32位整数某一位上1出现次数是否为1次、2次、3次,举例,假如:

  1. one = 1 --- 0x00000001 --- 00000000 00000000 00000000 00000001
  2. 则表示当前统计情况下最低位出现1的次数为1
  3. two = 3 --- 0x00000003 --- 00000000 00000000 00000000 00000011
  4. 则表示当前统计情况下最低位出现1的次数为2次,倒数第二位出现1的次数为2
  5. three = 4 --- 0x00000004 --- 00000000 00000000 00000000 00000100
  6. 则表示当前统计情况下最倒数第三位出现1的次数为3

大神们说one two three可以称之为掩码。

有了如上逻辑后,我们可以遍历所有的数字,对于每个数字,操作其所有的二进制位,来更新one two three三个数字。当我们遍历完所有数字时,由于除去target只出现一次外,其余元素都是以3为单位出现的,所以可以知道one中存储的二进制位代表的数字就是target。

对于实际代码中,one two three三者的更新,有以下两个版本,版本一是我自己想出来的,更通用,而且更接近于上面提出的更一般的问题的解决思路(代码一);版本二是网上大神们的代码,只能说更巧妙一些,但是实际上都一样(代码二)。详细请看代码部分中的注释。

以下来自牛客:https://www.nowcoder.com/questionTerminal/1097ca585245418ea2efd0e8b4d9eb7a
分析:除了某一个数只出现了1 or 2次(出现次数%3==1 or 2),其余都出现了三次(或整数倍)。也就是说,如果有 模3加法(异或为模2加法),那么就很简单了,直接把所有数字按位相加
Single
Number的本质,就是用一个数记录每个bit出现的次数,如果一个bit出现两次就归0,这种运算采用二进制底下的位操作^是很自然的。Single
Number II中,如果能定义三进制底下的某种位操作,也可以达到相同的效果,Single Number II中想要记录每个bit出现的次数,一个数搞不定就加两个数,用ones来记录只出现过一次的bits,用twos来记录只出现过两次的bits,ones&twos实际上就记录了出现过三次的bits,这时候我们来模拟进行出现3次就抵消为0的操作,抹去ones和twos中都为1的bits。

  1. public int singleNumber(int[] A) {
  2.         int ones = 0;//记录只出现过1次的bits
  3.         int twos = 0;//记录只出现过2次的bits
  4.         int threes;
  5.         for(int i = 0; i < A.length; i++){
  6.             int t = A[i];
  7.             twos |= ones&t;//要在更新ones前面更新twos
  8.             ones ^= t;
  9.             threes = ones&twos;//ones和twos中都为1即出现了3次
  10.             ones &= ~threes;//抹去出现了3次的bits
  11.             twos &= ~threes;
  12.         }
  13.         return ones; 
  14.     }

原文:https://blog.csdn.net/smile_watermelon/article/details/47748227

Leetcode 137 Single Number II 仅出现一次的数字的更多相关文章

  1. LeetCode 137. Single Number II(只出现一次的数字 II)

    LeetCode 137. Single Number II(只出现一次的数字 II)

  2. LeetCode 137 Single Number II(仅仅出现一次的数字 II)(*)

    翻译 给定一个整型数组,除了某个元素外其余的均出现了三次. 找出这个元素. 备注: 你的算法应该是线性时间复杂度. 你能够不用额外的空间来实现它吗? 原文 Given an array of inte ...

  3. [LeetCode] 137. Single Number II 单独数 II

    Given a non-empty array of integers, every element appears three times except for one, which appears ...

  4. [LeetCode] 137. Single Number II 单独的数字之二

    Given a non-empty array of integers, every element appears three times except for one, which appears ...

  5. 详解LeetCode 137. Single Number II

    Given an array of integers, every element appears three times except for one, which appears exactly ...

  6. leetcode 137. Single Number II ----- java

    Given an array of integers, every element appears three times except for one. Find that single one. ...

  7. Java [Leetcode 137]Single Number II

    题目描述: Given an array of integers, every element appears three times except for one. Find that single ...

  8. LeetCode 137 Single Number II 数组中除了一个数外,其他的数都出现了三次,找出这个只出现一次的数

    Given an array of integers, every element appears three times except for one, which appears exactly ...

  9. Java for LeetCode 137 Single Number II

    Given an array of integers, every element appears three times except for one. Find that single one. ...

随机推荐

  1. 【UOJ349】【WC2018】即时战略 LCT 动态点分治

    这是一道交互题 题目大意 有一棵\(n\)个点的树.最开始\(1\)号点是白的,其他点是黑的. 每次你可以执行一个操作:\(explore(x,y)\).要求\(x\)是一个白点.该函数会返回从\(x ...

  2. Android RadioGroup中设置默认选中RadioButton 后,选中两个的问题 解决方法

    项目中遇到多个RadioGroup中单选RadioButton ,设置了默认选中第一个 . 然后就 能选中两个RadioButton . . .. 我开始这样给设置默认选中一个的: for (int ...

  3. [CF52C]Circular RMQ【线段树】

    题目大意 给你一个环形数列,完成环形数列上区间加法和区间求最小值. 分析 算是一道比较水的线段树模板题. 如果l>r的话,那么修改l,n和1,r区间. 不然的话那么就修改l,r区间. 其他的基础 ...

  4. 英语考试 FZU - 2254 (最小生成树)

    先选一个单词出来完全自己背,然后从这个单词到其他各个单词所需要的精力看成距离,然后用最小生成树把这些单词连接起来,就是通过我现在选的这个单词到其他各个单词的最小精力,然后再加上把这个单词背起来的精力, ...

  5. deque双端队列容器

    //deque双端队列容器 //deque双端队列容器与vector一样,采用线性表顺序存储结构,但与vector不同的是, //deque采用的分块线性存储结构来存储数据,每块的大小一般为512字节 ...

  6. Python3 与 C# 扩展之~基础拓展

      上次知识回顾:https://www.cnblogs.com/dotnetcrazy/p/9278573.html 代码裤子:https://github.com/lotapp/BaseCode ...

  7. 洛谷P3959 宝藏

    去年NOIP第二毒瘤(并不)的题终于被我攻克了,接下来就只剩noip难度巅峰列队了. 首先说一下三种做法:随机化,状压DP和搜索. 前两种做法我都A了,搜索实在是毒瘤,写鬼啊. 有些带DFS的记忆化搜 ...

  8. A1147. Heaps

    In computer science, a heap is a specialized tree-based data structure that satisfies the heap prope ...

  9. JavaScript深入之变量对象

    前言 在上篇<javascript深入之执行上下文栈>中讲到,当javascript代码执行一段可执行代码(executable code)时,会创建对应的执行上下文(execution ...

  10. 使用ZXing.Net生成与识别二维码(QR Code)

    Google ZXing是目前一个常用的基于Java实现的多种格式的1D/2D条码图像处理库,出于其开源的特性其现在已有多平台版本.比如今天要用到的ZXing.Net就是针对微软.Net平台的版本.使 ...