【LeetCode】剑指 Offer 56. 数组中数字出现的次数 p275 -- Java Version
1. 题目介绍(56. 数组中数字出现的次数)
面试题56.:数组中数字出现的次数, 一共分为两小题:
- 题目一:数组中只出现一次的两个数字
- 题目二:数组中唯一只出现一次的数字
2. 题目1:数组中只出现一次的两个数字
题目链接:https://leetcode.cn/problems/shu-zu-zhong-shu-zi-chu-xian-de-ci-shu-lcof/
2.1 题目介绍
一个整型数组
nums里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)
【测试用例】:
示例1:
输入:nums = [4,1,4,6]
输出:[1,6] 或 [6,1]
示例2:
输入:nums = [1,2,10,4,1,4,3,3]
输出:[2,10] 或 [10,2]
【条件约束】:
限制:
- 2 <= nums.length <= 10000
2.2 题解 – 位运算(XOR)-- O(n)
时间复杂度O(n),空间复杂度O(1)
【解题思路】:
该问题是问在一个数组中找出 两个只出现一次的数字 ,那么我们可以先从这个数组中 只有一个数字只出现了一次 开始考虑:
- 首先我们可以想到 异或运算 的一个性质:任何一个数字异或它自己都等于0;也就是说,如果我们从头到尾依次异或数组中的每个数字,那么最终的结果刚好是那个只出现依次的数组,因为那些成对出现两次的数字全部在异或中抵消了(当然,这也是一个前提条件,要求 数组中的其它数字都是出现了两次,而不是三次或其他次,只能是 偶数次 才行)
……
既然,我们有了得到只出现一次数字的办法,那么我们就要想怎么求出两个只出现一次的数字:
- 我们可以试着将 原数组分成两个子数组 ,使得每个子数组包含一个只出现一次的数字,而其它数字都承兑出现两次。只要能够这样拆分成两个数组,那么我们就可以按照前面的办法分别找出两个只出现一次的数字
……
【实现策略】:
- 首先还是先进行无效输入的判断,判断数组长度
nums.length是否小于等于0,如果是,则说明是无效数据;- 定义变量
exclusiveOr,获取数组中所有元素的异或结果(该结果可以等同于 数组中两个唯一只出现一次的数字 的异或结果);- 我们可以根据这个异或结果(
exclusiveOr),去寻找这两个数字是在哪一位开始不同的,即从低位到高位,第一个Bit为1的位置;- 找到这个位置后,我们就可以根据这个位置进行分组了,我们将 该位为1 的数据分为一组,不为1 的分为一组,然后对其进行异或,最后剩下的数字就是我们要找到的两个数字了。
class Solution {// Solution1:异或分组和筛选public int[] singleNumbers(int[] nums) {// 无效输入判断if (nums.length <= 0) return null;// 将数组中所有元素进行异或int exclusiveOr = 0;for (int i = 0; i< nums.length; i++) {// 异或完成后,一样的会被抵消,只剩下不一样的两个数字,需要我们对其进行分组exclusiveOr ^= nums[i];}int indexBitIs1 = findFirstBitIs1(exclusiveOr);// 遍历数组并分组判断int[] res = new int[2];for (int j = 0; j < nums.length; j++) {if (isBit1(nums[j], indexBitIs1)) res[0] ^= nums[j];else res[1] ^= nums[j];}// 循环结束,返回结果return res;}// 从右向左寻找第一位为1的位数public int findFirstBitIs1(int num) {int indexFirstBitIs1 = 0;while ((num & 1) == 0 && (indexFirstBitIs1 < 32)) {num = num >> 1;indexFirstBitIs1++;}return indexFirstBitIs1;}// 判断输入的数字的indexBitIs1位是不是1public boolean isBit1(int num, int indexBitIs1) {num = num >> indexBitIs1;return (num & 1) != 0 ;}
}
代码简化:
class Solution {public int[] singleNumbers(int[] nums) {int x = 0, y = 0, n = 0, m = 1;for(int num : nums) // 1. 遍历异或n ^= num;while((n & m) == 0) // 2. 循环左移,计算 mm <<= 1;for(int num: nums) { // 3. 遍历 nums 分组if((num & m) != 0) x ^= num; // 4. 当 num & m != 0else y ^= num; // 4. 当 num & m == 0}return new int[] {x, y}; // 5. 返回出现一次的数字}
}
3. 题目2:
题目链接:https://leetcode.cn/problems/shu-zu-zhong-shu-zi-chu-xian-de-ci-shu-ii-lcof/
3.1 题目介绍
在一个数组
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
3.2 题解 – 位运算 – O(n)
时间复杂度O(n),空间复杂度O(1)
【解题思路】:
因为三个相同的数字的异或结果还是该数字,因此我们在这里就不能再使用异或运算解决该问题了,不过我们还是可以沿用位运算的思路:
- 如果一个数字出现三次,那么它的二进制表示的每一位(
0或者1)也出现三次;- 如果把所有出现三次的数字的二进制表示的每一位都分别加起来,那么每一位的和都能被
3整除;- 我们把数组中所有数字的二进制表示的每一位都加起来,如果某一位的和能被
3整除,那么那个只出现一次的数字二进制表示中对应的那一位是0;否则就是1.……
这种解法的时间效率是 O(n),我们需要一个长度为 32 的辅助数组存储二进制表示的每一位的和。当然,除此之外,还有其它解法:
- 从排序数组中找到只出现一次的数字,但排序需要额外的
O(nlogn)的时间;- 用一个哈希表来记录数组中每个数字出现的次数,但这个哈希表需要额外的
O(n)的空间;- 有限状态自动机:各二进制位的 位运算规则相同 ,因此只需考虑一位即可。如下图所示,对于所有数字中的某二进制位
1的个数,存在3种状态,即对3余数为0,1,2;该方法虽然效率较高,但也较难理解
class Solution {// Solution1:位运算public int singleNumber(int[] nums) {// 定义辅助数组 counts,用来存储二进制表示的每一位的和int[] counts = new int[32];// 循环遍历数组中的所有数for(int num : nums) {// 将该数的32位分别存入数组for(int j = 0; j < 32; j++) {counts[j] += num & 1;num = num >> 1;}}int res = 0, m = 3;for(int i = 0; i < 32; i++) {// 移位处理res <<= 1;// 如果 某一位的和能被 3 整除,那么那个只出现一次的数字// 二进制表示中对应的哪一位是0;否则就是1res |= counts[31 - i] % m;}return res;}
}
有限状态自动机:

class Solution {public int singleNumber(int[] nums) {int ones = 0, twos = 0;for(int num : nums){ones = ones ^ num & ~twos;twos = twos ^ num & ~ones;}return ones;}
}
4. 参考资料
[1] 剑指 Offer 56 - I. 数组中数字出现的次数(位运算,清晰图解)
相关文章:
【LeetCode】剑指 Offer 56. 数组中数字出现的次数 p275 -- Java Version
1. 题目介绍(56. 数组中数字出现的次数) 面试题56.:数组中数字出现的次数, 一共分为两小题: 题目一:数组中只出现一次的两个数字题目二:数组中唯一只出现一次的数字 2. 题目1:数组中…...
Zookeeper集群 + Fafka集群
目录 第一章Zookeeper 概述 1.1.Zookeeper 定义 1.2.Zookeeper 工作机制 1.3.Zookeeper 特点 1.4.Zookeeper 数据结构 1.5.Zookeeper 应用场景 1.6.Zookeeper 原理之选举机制 1.7.部署 Zookeeper 集群 总结 第二章消息队列概述 2.1消息队列需求原因 2.2消息队列的优…...
全国青少年电子信息智能创新大赛(复赛)python·模拟四卷
目录 一、编程题 答案解析如下: 下载文档打印做题: 全国青少年电子信息智能创新大赛(复赛)python模拟四卷 一、编程题 第一题:描述 班上有学生若干名,给出每名学生的年龄《整数),求班上所有学生的平均年龄,保留到小数点后两企 输入 第一行有一个整数n (1<= n...
Redis - 介绍与使用场景
简介 Redis 的全称是 Remote Dictionary Server,是一个使用 C 语言编写的、开源的(BSD 许可)高性能非关系型(NoSQL)的键值对数据库。 Redis 的数据是存储在内存中的,所以读写速度非常快,被广泛…...
Spark SQL实战(07)-Data Sources
1 概述 Spark SQL通过DataFrame接口支持对多种数据源进行操作。 DataFrame可使用关系型变换进行操作,也可用于创建临时视图。将DataFrame注册为临时视图可以让你对其数据运行SQL查询。 本节介绍使用Spark数据源加载和保存数据的一般方法,并进一步介绍…...
Django DRF - 权限Permissions
权限Permissions 权限控制可以限制用户对于视图的访问和对于具体数据对象的访问。 在执行视图的dispatch()方法前,会先进行视图访问权限的判断在通过get_object()获取具体对象时,会进行对象访问权限的判断 1.提供的权限 AllowAny 允许所有用户IsAuth…...
二叉树(OJ)
单值二叉树(力扣) ---------------------------------------------------哆啦A梦的任意门------------------------------------------------------- 我们来看一下题目的具体要求: 既然我们都学了二叉树了,我们就应该学会如何去…...
mysql中增删改成的练习
文章目录一、表的创建1.student表的数据2、课程表的数据course3、学生成绩表的数据二、操作序列1、查询计算机系cs的全体学生学号、姓名和性别2、检索选修了课程号为2的学生号和姓名3、检索至少选修了三门课以上的学生号4、检索选修了全部课程的学生5、在原表的基础上创建一个视…...
谈一谈Java的ThreadLocal
目录 先说原理: 再上代码: 运行结果: 先说原理: ThreadLocal 是一个本地线程副本变量工具类,它可以在每个线程中创建一个副本变量,每个线程可以独立地修改自己的副本变量,而不会影响其他线程…...
边缘检测与阈值分割
Canny [1] Canny Edge Detection. https://docs.opencv.org/3.4/da/d22/tutorial_py_canny.html [2] OpenCV Edge Detection ( cv2.Canny ). https://pyimagesearch.com/2021/05/12/opencv-edge-detection-cv2-canny/ 由John F. Canny提出 1、由于边缘检测容易受噪声影响&…...
QQ空间无敌装逼,复制下面的任一代码粘贴即可出现意想不到的图案。
复制下面的任一代码粘贴即可出现意想不到的图案。 打赏代码: [em]e10033[/em]{uin:123,nick: 打赏了你一个冰淇淋,who:1} [em]e10033[/em] 打赏了100000000000.00元红包 [em]e10011[/em] 赞代码:{uin:0000,nick: xx、xx、xx、xx、xx、xx、xx、xx、xx、xx、xx、x…...
必看!总结5种JavaScript异步解决方案
1.回调 回调简单地理解为一个函数作为参数传递给另一个函数,回调是早期最常用的异步解决方案之一。 回调不一定是异步的,也不直接相关。 举个简单的例子: function f1(cb) {setTimeout(() > {cb && cb();}, 2000); }f1(() >…...
JUC并发编程高级篇第四章之ThreadLocal(人手一份,天下安)
文章目录1、ThreadLocal的简介1.1、常见的面试题(也是本次的讲解的内容)1.2、什么是ThreadLocal1.3、ThreadLocal的所用1.4、没有出现ThreadLocal前后的变化1.5、ThreadLocal代码示例1.6、阿里巴巴对ThreadLocal的使用要求1.7、ThreadLocal的源码分析2、ThreadLocal…...
dump 定位分析
在缺少pdb的时候如何分析dump? windbgidaWindbg定位崩溃位置 通过windbg打开dump,并且分析dump !analyze -v 分析: 分析dump: !analyze -v错误原因:读取空指针错误线程:00001e04,可通过命令…...
(十二)排序算法-插入排序
1 基本介绍 1.1 概述 插入排序属于内部排序法,是对于欲排序的元素以插入的方式找寻该元素的适当位置,以达到排序的目的。 插入排序的工作方式非常像人们排序一手扑克牌一样。开始时,我们的左手为空并且桌子上的牌面朝下。然后,…...
elasticsearch 认知
1.大数据领域需要解决以下三个问题 如何存储数据 传统的关系数据库(MySQL、Oracle、和Access等)主导了20世纪的数据存储模式,但当数据量达到太字节级,甚至拍字节级时,关系型数据库表现出了难以解决的瓶颈问题。为了解决…...
《人体地图》笔记
《人体地图》 坂井建雄 著 孙浩 译 腹部通向大腿的隧道 腹部与大腿的分界点是大腿根部,即是腹股沟。 腹壁肌肉连结在腹股沟韧带上,腹壁肌肉包括三层,分别为腹外斜肌、腹内斜肌和腹横肌,每块肌肉都有一个张开的小孔,…...
java基础集合面试题
什么是集合 集合就是一个放数据的容器,准确的说是放数据对象引用的容器 集合类存放的都是对象的引用,而不是对象的本身 集合类型主要有3种:set(集)、list(列表)和map(映射)。 集合的特点 集合的特点主要有如下两点&…...
Vue学习-Vue入门
Vue学习 一、Vue入门 1、 引入Vue Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库…...
【项目】bxg基于SaaS的餐掌柜项目实战(2023)
基于SaaS的餐掌柜项目实战 餐掌柜是一款基于SaaS思想打造的餐饮系统,采用分布式系统架构进行多服务研发,共包含4个子系统,分别为平台运营端、管家端(门店)、收银端、小程序端,为餐饮商家打造一站式餐饮服务…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...
最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...
使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...
Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...
在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案
这个问题我看其他博主也写了,要么要会员、要么写的乱七八糟。这里我整理一下,把问题说清楚并且给出代码,拿去用就行,照着葫芦画瓢。 问题 在继承QWebEngineView后,重写mousePressEvent或event函数无法捕获鼠标按下事…...
MySQL:分区的基本使用
目录 一、什么是分区二、有什么作用三、分类四、创建分区五、删除分区 一、什么是分区 MySQL 分区(Partitioning)是一种将单张表的数据逻辑上拆分成多个物理部分的技术。这些物理部分(分区)可以独立存储、管理和优化,…...
前端高频面试题2:浏览器/计算机网络
本专栏相关链接 前端高频面试题1:HTML/CSS 前端高频面试题2:浏览器/计算机网络 前端高频面试题3:JavaScript 1.什么是强缓存、协商缓存? 强缓存: 当浏览器请求资源时,首先检查本地缓存是否命中。如果命…...
篇章二 论坛系统——系统设计
目录 2.系统设计 2.1 技术选型 2.2 设计数据库结构 2.2.1 数据库实体 1. 数据库设计 1.1 数据库名: forum db 1.2 表的设计 1.3 编写SQL 2.系统设计 2.1 技术选型 2.2 设计数据库结构 2.2.1 数据库实体 通过需求分析获得概念类并结合业务实现过程中的技术需要&#x…...
