题目链接

LeetCode 137. 只出现一次的数字 II[1]

题目描述

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次。找出那个只出现了一次的元素。

说明:
你的算法应该具有线性时间复杂度。你可以不使用额外空间来实现吗?

示例1

输入:
[2,2,3,2]
输出:
3

示例2

输入:
[0,1,0,1,0,1,99]
输出:
99

题解

逐位考虑

我们单独看二进制某一位,先不看单独的那个数,其他所有数字都出现了 3 次,所以那一位是 1 的个数一定是 3 的倍数。

再考虑这个出现一次的数,如果这一位是 1 ,那么这一位 1 的次数模 3 为 1 ,否则的话模 3 就是 0 。

那么就很简单了,统计一下有多少个数这一位上是 1 ,然后模 3 取余数,结果就是这个单独的数这一位上的值了。

遍历 32 位整数的每一位,就可以得到这个单独的数是多少了。

推广到一般情况:
如果其他数都出现了 次,一个数出现了一次。那么如果 是偶数,还是把所有的数异或起来就行了。如果 是奇数,那么统计每一位是 1 的个数,然后模 取余数就能得到那个单独的数了。

位运算

我们还可以用自动机来做这题,根据某一位 1 的个数,我们可以得到如下的状态自动机:

初始的时候在状态 0 (有 0 个 1),然后如果下一个数这一位是 1,就进入状态 1(有 1 个 1),接着如果下一个数这一位是 1,就进入状态 2(有 2 个 1),接着如果下一个数这一位是 1,就进入状态 3(有 3 个 1),最后如果再来了一个数这一位还是 1,就说明是一个新的数了,等价于回到了状态 1。而每个状态如果来的数这一位是 0 ,都会保持状态不变。

当然这个自动机还可以简化,注意观察可以发现状态 3 和状态 0 是等价的(输入 0 都保持不变,输入 1 都会进入状态 1)。所以我们将状态 1 和状态 3 合并为一个状态 0 ,得到如下的状态自动机:

因为一共有三个状态,所以我们需要用两个变量来表示状态。用 once 表示是否在状态 1,用 twice 来表示是否在状态 2 。那么两个变量都为 0 就表示在状态 0 。然后可以得到如下的状态转移表:

注意观察 once 只有两种情况下转移后为 1 。一种是 once=0, twice=0, x=1 ,另一种是 once=1, twice=0, x=0 。其他所有情况下 once 都转移为 0 。这两种情况都满足 x^once=1 并且 twice=0 ,所以 once 的转移就是 once = (x^once) & (~twice)

同理,观察 twice 只有两种情况下转移后为 1 。一种是 once=1, twice=0, x=1 ,另一种是 once=0, twice=1, x=0 。其他所有情况下 twice 都转移为 0 。这两种情况都满足 x^twice=1 并且 once^twice=1 ,所以 twice 的转移就是 twice = (x^twice) & (once^twice)但是!!!once 已经抢先一步转移过了,所以值已经变掉了,一个解决方法就是用临时变量保存一下前一个状态的 once 值。另一个方法就是,这两种情况下,once 都会转移到 0 ,所以判断条件直接用转移后的 once=0 就行了,随后转移就是 twice = (x^twice) & (~once)

代码

逐位考虑(c++)(代码有误,正确代码见留言第一条)

class Solution {
public:vector<int> missingTwo(vector<int>& nums) {int n = nums.size();int x = 0;for (auto i : nums) x ^= i;for (int i = 1; i <= n+2; ++i) x ^= i;int lb = x & -x;int y = 0;for (auto i : nums) {if (i&lb) y ^= i;}for (int i = 1; i <= n+2; ++i) {if (i&lb) y ^= i;}return {y, y^x};}
};

位运算(c++)

class Solution {
public:int singleNumber(vector<int>& nums) {int once = 0, twice = 0;for (auto x : nums) {once = (once^x)&(~twice);twice = (twice^x)&(~once);}return once;}
};

相关题目

LeetCode 136. 只出现一次的数字[2]

LeetCode 面试题56 - I. 数组中数字出现的次数[3]

LeetCode 面试题 17.19. 消失的两个数字[4]

参考资料

[1]

LeetCode 137. 只出现一次的数字 II: https://leetcode-cn.com/problems/single-number-ii/

[2]

LeetCode 136. 只出现一次的数字: https://leetcode-cn.com/problems/single-number/

[3]

LeetCode 面试题56 - I. 数组中数字出现的次数: https://leetcode-cn.com/problems/shu-zu-zhong-shu-zi-chu-xian-de-ci-shu-lcof/

[4]

LeetCode 面试题 17.19. 消失的两个数字: https://leetcode-cn.com/problems/missing-two-lcci/

作者简介:godweiyang知乎同名华东师范大学计算机系硕士在读,方向自然语言处理与深度学习喜欢与人分享技术与知识,期待与你的进一步交流~

我的微信:weiyang792321264。有任何问题都可以在评论区留言,也欢迎加我微信深入沟通~

【每日算法Day 72】谷歌面试题:又双叒叕是位运算,最详细的自动机推导过程...相关推荐

  1. 消除左递归c++代码_【每日算法Day 85】图解算法:一行代码解决约瑟夫环的变体...

    题目链接 LeetCode 390. 消除游戏[1] 题目描述 给定一个从 到 排序的整数列表. 首先,从左到右,从第一个数字开始,每隔一个数字进行删除,直到列表的末尾. 第二步,在剩下的数字中,从右 ...

  2. 5道谷歌面试题:即使是天才也要怀疑自己能力了(附答案)

    全世界只有3.14 % 的人关注了 数据与算法之美 谷歌,美国的跨国科技企业,致力于互联网搜索.云计算.广告技术等领域,开发并提供大量基于互联网的产品与服务. 这样一家实力雄厚前景无量的公司是众多求职 ...

  3. 吴军《谷歌面试题:倒置英文句子》

    吴军<谷歌面试题:倒置英文句子> 问题是这么说的:给你一个英语的语句,比如"London bridge is falling down",把它完全倒装过来," ...

  4. python 旋转矩阵_【每日算法Day 93】不用额外空间,你会旋转一个矩阵吗?

    第 100 天时,我可能会对这 100 天以来的算法题进行一个总结,然后暂时停止更新 LeetCode 题解了. 下一步可能更新 NLP 相关算法了,非常感谢大家每天的支持. 题目链接 LeetCod ...

  5. 算法与数据结构——网易笔试题(一)

    算法题 13:二叉堆(网易2016实习研发工程师) 思路: ********************************************************************** ...

  6. leetcode第277题名流问题(谷歌面试题)

    leetcode第277题名流问题(谷歌面试题) 一点小小的感受: 看到这个题的时候,一拍脑瓜子,想的就是双层for循环,去找那唯一的一个名人,(也是我这个菜鸟唯一能想到的解题方式) /*** @au ...

  7. 【每日一看】数据分析面试题归纳整理总结

    [每日一看]数据分析面试题归纳整理总结 刷题方向 统计理论知识 业务思维逻辑 机器学习.数据挖掘.工具类 算法编程.SQL 其他 刷题方向 目前看到的面经总结为分五大块: 统计理论知识 业务思维逻辑 ...

  8. 中科院团队用算法追上谷歌“量子霸权”:谷歌量子处理器并没有比E级超算快...

    点击上方"视学算法",选择加"星标"或"置顶" 重磅干货,第一时间送达 边策 发自 凹非寺 量子位 报道 | 公众号 QbitAI 两年前, ...

  9. 装鸡蛋的鞋子java代码_Java实现 LeetCode 887 鸡蛋掉落(动态规划,谷歌面试题,蓝桥杯真题)...

    887. 鸡蛋掉落 你将获得 K 个鸡蛋,并可以使用一栋从 1 到 N 共有 N 层楼的建筑. 每个蛋的功能都是一样的,如果一个蛋碎了,你就不能再把它掉下去. 你知道存在楼层 F ,满足 0 < ...

  10. 【每日算法】C语言8大经典排序算法(2)

    接上文--->[每日算法]C语言8大经典排序算法(1) 二.插入类排序 插入排序(Insertion Sort)的基本思想是:每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的子文件中 ...

最新文章

  1. webform repeater
  2. IP地址的划分和配置路由
  3. 【原创】一种维护型项目升级打包的解决方案
  4. windows 7 PowerShell 笔记
  5. 关于灵魂安放,年轻人如何选择适合自己的城市呢?学长有话说
  6. iOS谁说我不能执行你
  7. 性能测试 - 响应 vs 延迟 vs 吞吐量 vs 负载 vs 扩展性 vs 压力 vs 健壮性
  8. 关于spring-data-jpa的排序问题
  9. ECS 还是轻量应用服务器,看完评测你就知道了?
  10. 数字电子技术基础(第六版)阎石 版 课后答案 课后题答案与解析 课后习题答案
  11. 处理:‘IplImage’ does not name a type; did you mean ‘image’?
  12. 机器学习算法(一) K-Means算法简述以及在MNIST上的聚类实现
  13. es7 如何从项目resource读取index的mapping、setting.json文件
  14. Hyper-v 实现与虚拟机共享文件夹
  15. 我的世界服务器物品管道,物品导管 (Item Conduit)
  16. Insomnia下载
  17. 天津成考计算机水平考试,天津市成考《计算机基础考试大纲》(高中起点)
  18. MathType 6.9中平行四边形符号如何输入
  19. 多商户商城系统功能拆解02讲-平台端工作台
  20. 模拟IC设计入门——CMOS运算放大器设计

热门文章

  1. Java魔法堂:解读基于Type Erasure的泛型
  2. Excel 使用ODBC 连接mysql 5.0
  3. 金融IT和ERP,哪个更有前途?
  4. 查看windows电脑CPU核心数,线程数
  5. Android笔记:触摸事件的分析与总结----TouchEvent处理机制
  6. 转:程序员从初级到中级10个秘诀
  7. C++笔记之CopyFile和MoveFile的使用
  8. 站立会议(11月21日)
  9. 【洛谷P3369】【模板】普通平衡树题解
  10. fastjson使用-- @JSONField使用(转)