这是一系列位运算的题目,本文将由浅入深,先从最简单的问题开始:

问题1:

一个数组中只有一个数字出现过1次,其余数字都出现过两次,请找到那个只出现1次的数字。要求时间复杂度是 \(O(n)\),空间复杂度是 \(O(1)\)。

解法:

考虑到位运算中的异或运算,一个数字和它自己做异或,结果为0。所以只需要遍历整个数组,挨个异或,最后得到的结果就是那个只出现1次的数字。

class Solution {
public:
vector<int> singleNumbers(vector<int>& nums) {
int res = 0;
for (auto num : nums) {
res ^= num;
}
return res;
}
};

问题2:

一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是 \(O(n)\),空间复杂度是 \(O(1)\)。

解法:

与问题 1 的区别在于,这个问题中有两个出现次数为 1 的数字。可以将数组分成两个子数组,每个子数组中各含一个只出现 1 次的数字。具体做法为:

  • 对所有数字求异或,得到的结果即为 res
  • 保留 res 中的一个为 1 的数位,其余数位都变成 0,可以用 res & -res 保留最低位的 1,记为 div
  • 将数组中的每个数字和 div 做异或,按照结果为0或1分成2组,这样相同的数字都会被分到同一组,而那两个只出现 1 次的数字会被分到不同的组
  • 按组再做异或,同问题1,得到答案。

实际操作中不需要真正分组,只需要用两个变量 ab 记录两个组的异或值即可。

class Solution {
public:
vector<int> singleNumbers(vector<int>& nums) {
int res = 0;
for (auto num : nums) {
res ^= num;
}
int a = 0, b = 0;
int div = res & -res;
for (auto num : nums) {
if (div & num) {
a ^= num;
} else {
b ^= num;
}
}
return {a, b};
}
};

问题3:

在一个数组 nums 中除一个数字只出现一次之外,其他数字都出现了三次。请找出那个只出现一次的数字。

解法:

参考:K神的题解

如下图所示,考虑数字的二进制形式,对于出现三次的数字,各二进制位 出现的次数都是 3 的倍数。因此,统计所有数字的各二进制位中 1 的出现次数,并对 3 求余,结果则为只出现一次的数字。

class Solution {
public:
int singleNumber(vector<int>& nums) {
vector<int> digit(32); // 记录所有数字每个数位上1出现的次数之和
for (auto num : nums) { // 遍历每个数字
for (int i = 0; i < 32; i++) { // 遍历每个数位
digit[i] += num & 1; // num & 1 得到该数位是否为1
num >>= 1; // 获得下一个数位
}
}
int ans = 0, m = 3;
for (int i = 31; i >= 0; i--) {
//倒着遍历digigt数组,因为高数位在大下标位置
ans <<= 1; // ans左移1位
ans |= digit[31 - i] % m; // 每个数位对m取余后再和ans做或运算
}
return ans;
}
};

上面的代码只需要修改求余数值 \(m\) ,即可实现解决除了一个数字之外,其余数字都出现 \(m\) 次的通用问题。

【位运算】剑指offer 56. 数组中数字出现的次数的更多相关文章

  1. [剑指Offer]56-数组中数字出现的次数(位运算)

    题目一 数组中只出现一次的数字 题目 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字 题解 异或. 先考虑:数组中只有一个数字只出现了一次,其他数字都出现了 ...

  2. 剑指offer——62数组种数字出现的次数

    题目描述 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字. 题解: 我们想到异或运算的一个性质:任何一个数字异或它自己都等于0.也就是说,如果我们从头到尾依 ...

  3. 【剑指Offer】数组中只出现一次的数字 解题报告(Python)

    [剑指Offer]数组中只出现一次的数字 解题报告(Python) 标签(空格分隔): 剑指Offer 题目地址:https://www.nowcoder.com/ta/coding-intervie ...

  4. 剑指Offer:数组中出现次数超过一半的数字【39】

    剑指Offer:数组中出现次数超过一半的数字[39] 题目描述 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如,输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于这 ...

  5. 《剑指offer》数组中只出现一次的数字

    本题来自<剑指offer> 数组中只出现一次的数字 题目: 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字. 思路: 思路一:在<剑指of ...

  6. 剑指 Offer 51. 数组中的逆序对 + 归并排序 + 树状数组

    剑指 Offer 51. 数组中的逆序对 Offer_51 题目描述 方法一:暴力法(双层循环,超时) package com.walegarrett.offer; /** * @Author Wal ...

  7. 剑指 Offer 39. 数组中出现次数超过一半的数字 + 摩尔投票法

    剑指 Offer 39. 数组中出现次数超过一半的数字 Offer_39 题目描述 方法一:使用map存储数字出现的次数 public class Offer_39 { public int majo ...

  8. 剑指 Offer 03. 数组中重复的数字

    剑指 Offer 03. 数组中重复的数字 找出数组中重复的数字. 在一个长度为 n 的数组 nums 里的所有数字都在 0-n-1 的范围内.数组中某些数字是重复的,但不知道有几个数字重复了,也不知 ...

  9. 菜鸟刷题路:剑指 Offer 03. 数组中重复的数字

    剑指 Offer 03. 数组中重复的数字 哈希表/set class Solution { public int findRepeatNumber(int[] nums) { HashSet< ...

随机推荐

  1. jQuery--基本过滤选择器

    1.基本过滤选择器介绍 基本过滤器: :first     获取数组中第一个元素 :last      获取数组中最后一个 :eq(selector) 获取指定索引 :gt(index)     大于 ...

  2. Oracle入门基础(八)一一数据处理

    SQL> SQL的类型 SQL> 1.DML(Data Manipulation Language 数据操作语言): select insert update delete SQL> ...

  3. java的arrays

    java.util.Arrays 是一个于数组相关的工具类,里面提供大佬的静态方法,用来实现数组常见的操作 public staic String toString(数组)  将参数数组编程字符串,默 ...

  4. List、Set、Map 和 Queue 之间的区别?

    List 是一个有序集合,允许元素重复.它的某些实现可以提供基于下标值的常量 访问时间,但是这不是 List 接口保证的.Set 是一个无序集合.

  5. 学习heartbeat-04 原理及部署

    1. Heartbeat介绍 1.1 Heartbeat作用 通过它可以将资源(IP及程序服务等资源)从一台故障计算机快速转移到另一台运转正常的机器继续提供服务,在实际生产应用场景中,heartbea ...

  6. 调用高德地图web api 规划路线

    实现地图输出,出发地与目的地路线,效果如下 具体代码如下 <!doctype html> <html> <head> <meta charset=" ...

  7. getch()函数的使用方法及其返回值问题

    getch()函数依赖于头文件 conio.h .会在windows平台下从控制台无回显地取一个字符,并且返回读取到的字符. 然而,我在实际用这个函数才发现getch()这个函数并不简单. getch ...

  8. 《基于.NET Core构建微服务》系列文章(更新至第6篇,最新第7篇,已发布主页候选区)

    原文:Building Microservices On .NET Core – Part 1 The Plan 时间:2019年1月14日 作者:Wojciech Suwała, Head Arch ...

  9. 阿里云场景化阿里云企业数字化转型售前方法PSA

    阿里云场景化阿里云企业数字化转型售前方法PSA 目录 01 课程收获 理解企业数字化转型的概念.内涵.本质 了解企业数字化转型的要点.目标和切入点 掌握数字化转型项目售前阶段实践方法 场景化方案 阿里 ...

  10. Linux 0.11源码阅读笔记-文件管理

    Linux 0.11源码阅读笔记-文件管理 文件系统 生磁盘 未安装文件系统的磁盘称之为生磁盘,生磁盘也可以作为文件读写,linux中一切皆文件. 磁盘分区 生磁盘可以被分区,分区中可以安装文件系统, ...