惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

IT之家
IT之家
Recent Announcements
Recent Announcements
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
The GitHub Blog
The GitHub Blog
MyScale Blog
MyScale Blog
爱范儿
爱范儿
GbyAI
GbyAI
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
美团技术团队
Y
Y Combinator Blog
博客园 - 叶小钗
Apple Machine Learning Research
Apple Machine Learning Research
Martin Fowler
Martin Fowler
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
罗磊的独立博客
M
MIT News - Artificial intelligence
博客园 - Franky
V
Visual Studio Blog
I
InfoQ
V
V2EX
Hugging Face - Blog
Hugging Face - Blog
腾讯CDC
博客园 - 司徒正美
L
LangChain Blog

OhYee 博客

小鹏辅助驾驶测评|OhYee 博客 小鹏非支持手机开启自动解锁|OhYee 博客 使用函数计算实现 301 重定向|OhYee 博客 针对 HTML 内容使用 Ant Design 图片弹框|OhYee 博客 博客进程泄露及僵尸进程解决|OhYee 博客 蓝易云服务器体验|OhYee 博客 SSH 调起本地 VSCode|OhYee 博客 【2022 秋招内推】阿里云后端研发工程师|OhYee 博客 使用函数计算获取 IP 地址信息|OhYee 博客 正确获取客户端 IP/HTTP Header 也可能重复|OhYee 博客 评测 Oculus Quest2 及 BigScreen|OhYee 博客 NextJS 热重载保留状态|OhYee 博客 如何优雅地贴 gist 代码|OhYee 博客 Linux 精细化文件权限|OhYee 博客 VSCode 容器开发环境|OhYee 博客 Clash 的不兼容更新排查|OhYee 博客 Zeek 导出 PCAP|OhYee 博客 记一次 ssh 配置问题|OhYee 博客 Git Commit 规范化工具|OhYee 博客 谈谈《星之卡比-探索发现》|OhYee 博客 VSCode 快捷键绑定 Shell 命令|OhYee 博客 ASN.1 语法及 X.509 证书格式解析解析|OhYee 博客 腾讯企业邮箱忽略 MX 记录发信|OhYee 博客 Chrome/Edge 标签组插件|OhYee 博客 【应届内推】阿里云后端研发工程师|OhYee 博客 损坏的 Typecho 备份处理为 JSON|OhYee 博客 VS Code VIM 插件高效使用|OhYee 博客 SSH 正反向代理|OhYee 博客 Let's Encrypt 根证书过期引发的问题|OhYee 博客 OpenWRT 忽略内核依赖|OhYee 博客
LeetCode 137. 只出现一次的数字 II|OhYee 博客
2021-05-01 · via OhYee 博客

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

题目描述

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

示例 1:
输入:nums = [2,2,3,2]
输出:3

示例 2:
输入:nums = [0,1,0,1,0,1,99]
输出:99

题解

如果题面是 “除某个元素仅出现一次外,其余每个元素都出现偶数次”,那么就是一道很经典得 O(n)O(n) 的异或
但是这里不是偶数次,而是三次,异或并不能处理这种状况,但是仍然可以采用类似的思路进行处理

这种题目,对于多位和一位,我们的处理逻辑是一致的
尽管异或的特性,只能处理偶数次,但是如果可以用另一个位来记录状态,那么就可以实现对 33 的倍数次的处理。这样就解决了问题
假定用 ab 记录所处的状态(这里虽然严格要求 33 次,但是由于不同的数字可能会在同一位是 11,因此应该考虑为 33 的倍数次)

  • 00: 3k3k
  • 01: 3k+13k+1
  • 10: 3k+23k+2

从中,我们只需要出现 3k+13k+1 次的情况。为了方便后续处理,这里取 01 作为 3k+13k+1 次的状态。理论上而言,状态的设定是任意的,但是如果使用 01 存储,那么在输出结果为 3k+13k+1 次的数时,可以直接输出 b(因为其他不符合的情况,b 都是 00
需要特别注意的是,我们的状态中没有 11,他也不会出现在我们的数据中,因此不需要考虑

那么现在需要考虑的是,如果对这个状态进行转移

首先考虑新的数字是 00 的情况,00 意味着没有新数字,那么不需要改变,只需要保留原来的结果即可;接下来是新数字为 11,也即状态需要执行 +1+1 擦做,00 将转换为 0101 将转换为 1010 将转换为 00

这里可以看作下表的形式

ab c 新的ab
0000 00 0000
0101 00 0101
1010 00 1010
0000 11 0101
0101 11 1010
1010 11 0000

接下来就是实现 ab 的转移了,可以使用一种很偷懒的方式进行转移:使用 “与运算” 和 “或运算” 可以实现位运算中的 if
对于 a 而言,当 c00 时,只有 a11 时输出 11;当 c11 时,只有 b11 时输出 11。也即 a = (~c & a) | (c & b)
对于 b 而言,当 c00 时,只有 b11 时输出 11;当 c11 时,只有 ab 都为 00 时输出 11。也即 b = (~c & b) | (c & (~a & ~b))

代码

func singleNumber(nums []int) int {
    a, b := 0, 0
    for _, c := range nums {
        a, b = (^c & a) | (c & b), (^c & b) | (c & ^a & ^b)
    }
    return b
}