剑指 Offer 56 - II. 数组中数字出现的次数 II
题目描述
在一个数组 nums 中除一个数字只出现一次之外,其他数字都出现了三次。请找出那个只出现一次的数字。
示例1:
输入:nums = [3,4,3,3]
输出:4
示例2:
输入:nums = [9,1,7,9,7,9,7]
输出:1
限制:
1 <= nums.length <= 10000
1 <= nums[i] < 2^31
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/shu-zu-zhong-shu-zi-chu-xian-de-ci-shu-ii-lcof
方法一:map
class Solution {
public:
int singleNumber(vector<int>& nums) {
map<int, int> nums_map;
for(int num : nums)
nums_map[num]++;
for(auto &key : nums_map)
if(key.second == 1)
return key.first;
return 0;
}
};
这个方法不用多说,时间复杂度和空间复杂度均为\(O(n)\)。
方法二:位运算
基本思路:int
值为32位,由于仅有一个数字只出现了1次,其余数字均出现了3次,统计每一位上1出现的次数,并对3求余,可得目标数字的二进制表示。
class Solution {
public:
int singleNumber(vector<int>& nums) {
if(nums.empty()) return 0;
int result = 0;
// 对32位分别统计1出现的次数
for(int i = 0; i < 32; i++) {
int count = 0;
int index = 1 << i;
// 遍历数组中的每个数字,统计第i位上是否为1
for(int num : nums) {
if((index & num) != 0)
count++;
}
// 若count对3求余结果为1,则目标数字的该位为1,使用按位或运算记入result
if(count % 3 == 1)
result |= index;
}
return result;
}
};
时间复杂度\(O(n)\),空间复杂度\(O(1)\)。
方法三:位运算进阶
方法二在时间复杂度和空间复杂度上都已经很好了,但还有加速的空间,由于方法二中对每一个数字都需要进行32次统计,则时间复杂度\(O(n)\)有常系数32,思考办法将常系数32降低。
- 我们的目的没有改变,仍然是统计第\(i\)位上1出现的次数\(n_i\),准确的说是统计\((n_i\% 3)\)。
- 每一位上1出现的次数对3的余数可以表示为0,1,2三种情况,但是3中情况无法使用一位二进制数字来表示,因此我们需要扩充至两位二进制数字
00 01 10
,最后得到64位的结果的形式如下:
00 01 10 ... 00 10 ...
low
表示低位,high
表示高位,真值表如下:
high | low | digit | high | low |
---|---|---|---|---|
→ | ||||
0 | 0 | 0 | 0 | 0 |
0 | 1 | 0 | 0 | 1 |
1 | 0 | 0 | 1 | 0 |
0 | 0 | 1 | 0 | 1 |
0 | 1 | 1 | 1 | 0 |
1 | 0 | 1 | 0 | 0 |
- 低位的求值方法为:
if(high == 0)
if(digit == 0)
low = 0;
else
low = 1;
else
low = 0;
使用异或运算表达:
if(high == 0)
low = (low ^ digit);
else
low = 0;
稍加整理:
low = (low ^ digit) & (~high)
- 高位的求值方法为:
在计算高位之前,要考虑到此时的低位已经是经过运算之后的新的低位。
if(low == 0)
if(digit == 0) // 对应真值表第三行和第五行
high = high;
else // 对应真值表第七行和第八行
high = ~high;
else // 对应真值表第四行和第六行
high == 0;
使用异或运算表达:
if(low == 0)
high = (high ^ digit);
else
high = 0;
稍加整理:
high = (high ^ digit) & (~low);
最终代码实现如下:
class Solution {
public:
int singleNumber(vector<int>& nums) {
int low = 0;
int high = 0;
for(int num : nums) {
low = (low ^ num) & (~high);
high = (high ^ num) & (~low);
}
return low;
}
};
时间复杂度\(O(n)\),空间复杂度\(O(1)\)。
剑指 Offer 56 - II. 数组中数字出现的次数 II的更多相关文章
- 剑指 Offer 56 - I. 数组中数字出现的次数 + 分组异或
剑指 Offer 56 - I. 数组中数字出现的次数 Offer_56_1 题目描述 解题思路 java代码 /** * 方法一:数位方法 */ class Offer_56_1_2 { publi ...
- 剑指 Offer 56 - I. 数组中数字出现的次数
题目描述 一个整型数组 nums 里除两个数字之外,其他数字都出现了两次.请写程序找出这两个只出现一次的数字.要求时间复杂度是\(O(n)\),空间复杂度是\(O(1)\). 示例1: 输入:nums ...
- 剑指 Offer 56 - II. 数组中数字出现的次数 II + 位运算
剑指 Offer 56 - II. 数组中数字出现的次数 II Offer_56_2 题目详情 解题思路 java代码 package com.walegarrett.offer; /** * @Au ...
- 《剑指offer》面试题56 - II. 数组中数字出现的次数 II
问题描述 在一个数组 nums 中除一个数字只出现一次之外,其他数字都出现了三次.请找出那个只出现一次的数字. 示例 1: 输入:nums = [3,4,3,3] 输出:4 示例 2: 输入:nums ...
- 《剑指offer》旋转数组中的最小数字
本题来自<剑指offer> 旋转数组中的最小数字 题目: 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素. 例 ...
- 【剑指Offer】旋转数组中的最小数字 解题报告(Python)
[剑指Offer]旋转数组中的最小数字 解题报告(Python) 标签(空格分隔): LeetCode 题目地址:https://www.nowcoder.com/ta/coding-intervie ...
- 面试题56 - I. 数组中数字出现的次数
面试题56 - I. 数组中数字出现的次数 一个整型数组 nums 里除两个数字之外,其他数字都出现了两次.请写程序找出这两个只出现一次的数字.要求时间复杂度是O(n),空间复杂度是O(1). 示例 ...
- LeetCode 面试题56 - I. 数组中数字出现的次数 | Python
面试题56 - I. 数组中数字出现的次数 题目 一个整型数组 nums 里除两个数字之外,其他数字都出现了两次.请写程序找出这两个只出现一次的数字.要求时间复杂度是O(n),空间复杂度是O(1). ...
- 力扣Leetcode 面试题56 - I. 数组中数字出现的次数
面试题56 - I. 数组中数字出现的次数 一个整型数组 nums 里除两个数字之外,其他数字都出现了两次.请写程序找出这两个只出现一次的数字.要求时间复杂度是O(n),空间复杂度是O(1). 示例 ...
随机推荐
- Flutter 入门
- 11、Composite 组合模式 容器与内容的一致性(抽象化) 结构型设计模式
1.Composite模式定义 组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象.组合模式依据树形结构来组合对象,用来表示部分以及整体层次.这 ...
- PHP基础之排序
前言 之前简单介绍了流程控制,函数,数组等.有兴趣的可以看看. PHP入门之类型与运算符 PHP入门之流程控制 PHP入门之函数 PHP入门之数组 接下来介绍一下排序,排序是将一组数据,依指定的顺序进 ...
- 算法学习笔记:2-SAT
SAT 是适定性(Satisfiability)问题的简称.一般形式为 k - 适定性问题,简称 k-SAT.而当 \(k>2\) 时该问题为 NP 完全的.所以我们只研究 \(k=2\) 的情 ...
- sftp与ftp的区别
SFTP和FTP非常相似,都支持批量传输(一次传输多个文件),文件夹/目录导航,文件移动,文件夹/目录创建,文件删除等.但还是存在着差异,下面我们来看看SFTP和FTP之间的区别. 1. 安全通道FT ...
- C#LeetCode刷题之#888-公平的糖果交换(Fair Candy Swap)
问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3758 访问. 爱丽丝和鲍勃有不同大小的糖果棒:A[i] 是爱丽丝 ...
- C#LeetCode刷题之#830-较大分组的位置(Positions of Large Groups)
问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3750 访问. 在一个由小写字母构成的字符串 S 中,包含由一些连 ...
- JavaScript apply使用
call 和 apply 作用: 都是为了改变某个函数运行的context上下文而存在的,为了改变函数体内部 this的指向 JavaScript函数存在定义时上下文和运行时上下文, 上下文(cont ...
- Kinect+unity 实现体感格斗闯关小游戏
文章目录 项目地址 1 项目概况 1.1 项目简介 1.2 项目目的 1.3 主要技术 2 设计 2.1 基本概念 2.2 框架 2.3 算法 2.4 模型 2.5 调查问卷 3 实现 3.1 技术难 ...
- 用python爬取B站在线用户人数
最近在自学Python爬虫,所以想练一下手,用python来爬取B站在线人数,应该可以拿来小小分析一下 设计思路 首先查看网页源代码,找到相应的html,然后利用各种工具(BeautifulSoup或 ...