题目

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

  • 输入:nums = [4,1,4,6]
  • 输出:[1,6] 或 [6,1]

其实看到他要求的空间复杂度为O(1)代表不能使用类似于HashMap这种数据结构的解法了,我当时也有点懵比,那要怎么做呢?想了半天还是看看评论区大神的解题思路吧。

思路

在做这道题之前你需要知道 异或运算符的性质。也就是^
异或:相同为0,不同为1
举个例子:3 ^ 5

3的二进制:0 0 1 1
5的二进制:0 1 0 1
异或结果: 0 1 1 0

异或满足交换律,结合律,自反性

  • 交换律:a ^ b = b ^ a
  • 结合律:(a ^ b) ^ c = a ^ (b ^ c)
  • 自反性: A XOR B XOR B = A xor 0 = A
  • x ^ x = 0 ; x ^ 0 = x(任何数与他自身做异或等于0,任意数与0做异或还是他本身)

由此结合题目我们可以从数字的异或入手。

因为只有两个数字只出现过一次,其余的数都出现了两次,所以对这个数组中的所有数字进行异或操作的结果也就是对 只出现一次的两个数进行异或。我们把这俩数字异或的结果设为 res.

现在关键是怎样把他们分开?
因为两个数字如果相同,那么他们的二进制的每一位都相同,如果两个数不同,那么他们的二进制中肯定有不同的那一位。

由于异或的性质是,同一位相同则为 0,不同则为 1. 我们将所有数字异或的结果一定不是 0,也就是说至少有一位是 1.

我们随便取一个,分组的依据就来了, 就是你取的那一位是 0 分成 1 组,那一位是 1 的分成一组。

方法一:

int h = 1;
while((h&res)==0){
h=h<<1;
}
//从res中找第一个不是0的那一位(从右往左)

方法二:

int h = res&(-res);
//这个需要试一下,相反数的二级制计算时:先取反,再加一,在进行&就能找到res的二级制中第一个 1
//例如 5 的二进制是 0101 -5的二进制是 1011 进行&得到 0001,所以从右往左,5的二进制的第一位是 1.

我们将这两个分开以后,只需要进一步判断数组中的元素和 h 做与 运算

如果n(这里指数组中的元素)& h == 0,代表当前元素的这一位上是0,
如果 (n & h )==n那么就代表当前元素这一位上是1,这样就把整个数组分开了,同时两个只出现一次的数字也分开了。

分成两组后,最后进行异或运算,剩余的结果就分别是只出现1次的那两个数。(因为 x ^ x = 0, x ^ 0 = x)

代码

public int[] singleNumbers(int[] nums) {
int res = 0;// 用来保存两个只出现一次的数的异或结果
for(int i: nums){
res^=i;
}
int h=res&(-res);//从右往左找到第一个是1的位 int a=0,b=0;//用来保存分组后的结果 for(int n:nums){
if((n & h)==0){
a^=n;
}else{
b^=n;
}
}
return new int[]{a,b};
}

以上有理解不到位的地方欢迎各位指出!

剑指offer-56数组中数字出现的次数的更多相关文章

  1. 【位运算】剑指offer 56. 数组中数字出现的次数

    这是一系列位运算的题目,本文将由浅入深,先从最简单的问题开始: 问题1: 一个数组中只有一个数字出现过1次,其余数字都出现过两次,请找到那个只出现1次的数字.要求时间复杂度是 \(O(n)\),空间复 ...

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  9. 剑指 Offer 39. 数组中出现次数超过一半的数字

    剑指 Offer 39. 数组中出现次数超过一半的数字 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字. 你可以假设数组是非空的,并且给定的数组总是存在多数元素. 示例 1: 输入: [ ...

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

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

随机推荐

  1. Springboot mini - Solon详解(三)- Solon的web开发

    Springboot min -Solon 详解系列文章: Springboot mini - Solon详解(一)- 快速入门 Springboot mini - Solon详解(二)- Solon ...

  2. mybatis逆向工程运行

    命令: mvn mybatis-generator:generate 项目结构: generatorConfig.xml内容示例 <?xml version="1.0" en ...

  3. Typora快捷使用方式

    快捷使用: 1.一级标题 # + 空格 + 内容 2.六级标题 # + 空格 + 内容 3.有序序号 1. + 空格 + 内容 4.无序序号 -+ 空格.*+空格.++空格 5.代码块 ```pyth ...

  4. 架构师基础技能-搭建gitLab

    前言 想要成为一名架构师,一定要有从无到有搭建环境的能力,这是作为架构师的基础技能,而gitLab服务器的搭建一定又是重中之重. 相信很多小伙伴的公司也在使用gitLab,但都是你们公司的架构师搭建好 ...

  5. js上 十二、函数初步-1

    11-1.引入(认识函数) ​ 引入: 说起函数,其实我们并不陌生,在初中数学中我们就接触过函数:例如我们所学的 y = 2X+1 ; 这是一个二元一次方程,也是我们数字中的函数: ​ 当我们每次输入 ...

  6. 在IDEA中使用JDBC获取数据库连接时的报错及解决办法

    在IDEA中使用JDBC获取数据库连接时,有时会报错Sat Dec 19 19:32:18 CST 2020 WARN: Establishing SSL connection without ser ...

  7. angular8 页面滚动到某一个特定位置

    背景:使用angular8安装的 Fuse-v8.0.0-demo 后台的框架 锚点: id='nearby' 流程:无论是点击触发方法也好,还是直接调用方法也好,这里只写 引入: import {C ...

  8. kafka rebalance解决方案 -incremental cooperative协议和static membership功能

    apache kafka的重平衡(rebalance),一直以来都为人诟病.因为重平衡过程会触发stop-the-world(STW),此时对应topic的资源都会处于不可用的状态.小规模的集群还好, ...

  9. iOS 调用系统拍照遇到的坑

    iOS 11之前用的一套图片选择器框架,之前一直没问题,iOS11之后拍照后回调失败......,打断点方法完全执行,也能回调成功:但是去掉断点又恢复不能会调的问题.困扰了一下午,愣是没有解决.后来把 ...

  10. net core 3.1使用ElasticSearch 全文搜索引擎

    ElasticSearch 是一个开源的搜索引擎,建立在一个全文搜索引擎库 Apache Lucene 基础之上. Lucene 可以说是当下最先进.高性能.全功能的搜索引擎库,无论是开源还是私有. ...