java数据结构与算法刷题-----LeetCode540. 有序数组中的单一元素

news2024/9/29 17:28:22
java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.csdn.net/grd_java/article/details/123063846

文章目录

    • 1. 异或运算
    • 2. 全数组二分查找+异或奇偶
    • 3. 偶数下标二分查找

在这里插入图片描述

1. 异或运算

解题思路:时间复杂度O( n n n),空间复杂度O( 1 1 1)
  1. 利用异或操作,因为异或满足结合律和交换律
  2. 两个二进制位,相同的数异或结果为0,两个不同的数异或结果为1
  3. 而对与10进制,两个相同的数异或必然为0,因为两个10进制数,每位二进制数都相同,也就是a ^ a = 0
  4. 因此将数组中所有的数全部进行异或运算,出现两次的数都会为0
  5. 而任何数a ^ 0都等于a本身
  6. 因此例如aabcc这样的序列,想要找到中间那个出现次数一次的b,只需要异或即可

1、a^a = 0, 2、0^b = b, 3、b^c = b^c, 4、b ^c ^c = b^0 = b

代码

在这里插入图片描述

class Solution {
    public int singleNonDuplicate(int[] nums) {
        int a = nums[0];//异或操作,两个相同的数异或会归0,并且满足交换律
        for(int i = 1 ; i < nums.length; i++) a^=nums[i];
        return a;//最终所有出现两次的数会全部抵消,只剩下一个出现一次的数a
    }
}

2. 全数组二分查找+异或奇偶

解题思路:时间复杂度O( l o g 2 n log_2n log2n),空间复杂度O( 1 1 1)
  1. 利用整个数组的数字分配规律,来进行二分查找
  2. 因为整个数组只有一个元素x的个数是奇数—1个,其余都是偶数有2个。所有以x为中心,两边都是偶数个元素。而x左边的元素会保证偶数分配规律(每个数字第一次出现都是偶数下标),而x只有一个,破坏了规律,x右边的变成符合奇数规律
  3. 因此可以利用这个偶数规律,x左边的元素,从偶数0开始,依次判断是否nums[y] = nums[y+1]即可,其中y是偶数
  4. 而x右边的元素,会被x破坏偶数关系,将会从奇数开始两个两个分布,因此x右边判断是否满足nums[z] = nums[z+1]即可,其中z是奇数
  5. 有了上面的原理后,我们就可以利用这个信息,x左边的数字分配规律为,如果是偶数下标一定是第一个,如果是奇数下标一定是这个数字的第二个。
  6. 也就是说如果mid为偶数,比较nums[mid]和nums[mid+1]. 如果是奇数比较nums[mid-1]和nums[mid]
  7. 如果比较结果为相等,说明满足偶数规律,也就是mid < x.mid还在x的左边,因此调整左边界

使用的异或奇偶性质参考:

位运算https://blog.csdn.net/grd_java/article/details/136119268
  1. 如果mid是偶数,mid +1 操作相当于 mid ^ 1

例如2是偶数,二进制为0010,异或1(二进制0001)结果为0011.

  1. 如果mid是奇数,mid - 1 操作相当于 mid ^ 1

例如1是奇数,二进制为0001,异或1(二进制0001)结果为0000.

代码

在这里插入图片描述

class Solution {
    public int singleNonDuplicate(int[] nums) {
        int low = 0, high = nums.length - 1;//二分查找
        while (low < high) {
            int mid = (high - low) / 2 + low;//获取mid
            //因为整个数组只有一个元素x的个数是奇数1个,其余都是偶数有2个。所有以x为中心,两边都是偶数个元素
            //因此可以利用这个偶数规律,x左边的元素,从偶数0开始,依次判断是否nums[y] = nums[y+1]即可
            //而x右边的元素,会被x破坏偶数关系,将会从奇数开始两个两个分布,因此x右边判断是否满足nums[z] = nums[z+1]即可
            //有了上面的原理后,我们就可以利用这个信息,x左边的数字分配规律为,如果是偶数下标一定是第一个,如果是奇数下标一定是这个数字的第二个。
            //也就是说如果mid为偶数,比较nums[mid]和nums[mid+1]. 如果是奇数比较nums[mid-1]和nums[mid]
            //如果比较结果为相等,说明满足偶数规律,也就是mid < x.mid还在x的左边,因此调整左边界
            if (nums[mid] == nums[mid ^ 1]) {//如果是偶数mid和mid+1比,奇数mid和mid-1比
                low = mid + 1;
            } else {//如果不相等,说明不满足偶数规律,也就是mid >= x,调整右边界
                high = mid;
            }
        }
        return nums[low];//最后low将指向x位置
    }
}

3. 偶数下标二分查找

解题思路:时间复杂度O( l o g 2 n log_2n log2n),空间复杂度O( 1 1 1)
  1. 法二是整个数组去找。并没有完全利用偶数性质
  2. x虽然是打破偶数规则的数,但是其本身依然符合偶数规则(第一次出现是在偶数下标位置)
  3. 而x后面的元素全部因为x的影响,无法满足偶数规则
  4. 而且x也是第一个不满足nums[x] == nums[x+1]的数(x是偶数)。
  5. 因此这个问题变成了,找到第一个nums[x] != nums[x+1]的数(x是偶数)

简单来说,x是第一个满足nums[x] != numsx+1的数,那么x就是那个只出现1次的数。

其余逻辑和法二一样

如何保证所有数都是偶数?

  1. 如果当前数是奇数的话,让其-1。
  2. 如果当前数是偶数的话,让其-0.
  3. 通过与操作完成即可。也就是mid -= mid&1.

假设mid是偶数2,二进制为0010,2&1 = 0010 & 0001 = 0000.也就是mid&1 = 0.mid - 0 = mid。
假设mid是奇数3,二进制为0011,3&1 = 0011&0001 = 0001,也就是mid&1 = 1.mid -=mid&1 ==> mid -1

代码

在这里插入图片描述

class Solution {
    public int singleNonDuplicate(int[] nums) {
        int low = 0, high = nums.length - 1;
        while (low < high) {
            int mid = (high - low) / 2 + low;//二分查找
            mid -= mid & 1;//保证当前mid是偶数下标
            if (nums[mid] == nums[mid + 1]) {//如果满足nums[mid] == nums[mid + 1],说明现在mid<x
                low = mid + 2;//去mid右边找
            } else {//如果不满足,则mid>=x, 但是不能保证就是x,所以需要继续左边找
                high = mid;//去mid左边,直到找到x为止
            }
        }
        return nums[low];
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1550483.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python学习之-正则表达式

目录 前言&#xff1a;1.re.serach1.1例子&#xff1a; 2.re.match2.1示例1&#xff1a;2.2 示例2&#xff1a; 3.re.findall3.1 示例 4.re.fullmatch4.1 示例1&#xff1a;4.2 示例2: 5.re.split5.1 示例1:5.2 示例2&#xff1a;5.3 示例3&#xff1a; 6.re.sub6.1 示例&#…

puzzle(1122)连线迷宫

目录 一&#xff0c;连线迷宫-经典模式 1&#xff0c;规则 2&#xff0c;策略 3&#xff0c;调整的局部性 4&#xff0c;八连通端点的线条合并 taptap小游戏 迷宫解谜 连线迷宫模式 一&#xff0c;连线迷宫-经典模式 1&#xff0c;规则 2&#xff0c;策略 分2步&#x…

脚本应使用项目的主要语言编写

原文&#xff1a;Joo Freitas - 2024.03.24 这是我长时间以来的一个深感赞同的观点。 我参与过的几乎所有项目&#xff0c;都有我们编写的用于自动化重复性过程的脚本。然而&#xff0c;大多数脚本在几周后变得过时且难以维护&#xff0c;因为我们要么不再需要它们&#xff0…

Golang hash/crc32 库实战指南:从基础到优化

Golang hash/crc32 库实战指南&#xff1a;从基础到优化 引言理解CRC32hash/crc32库概览实战技巧数据校验性能优化多线程应用 错误处理与调试错误处理调试 实际案例分析结论 总结重点回顾 引言 在现代软件开发中&#xff0c;数据的完整性和安全性至关重要。无论是数据库存储、…

计算机组成原理 — 指令系统

指令系统 指令系统指令的概述指令的格式指令的字长取决于 操作数类型和操作种类操作数的类型数据在存储器中的存放方式操作类型 寻址方式指令寻址数据寻址立即寻址直接寻址隐含寻址间接寻址寄存器寻址寄存器间接寻址基址寻址变址寻址堆栈寻址 RISC 和 CISC 技术RISC 即精简指令…

K8s Pod亲和性、污点、容忍度、生命周期与健康探测详解(上)

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《Kubernetes航线图&#xff1a;从船长到K8s掌舵者》 &#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 在上一章节中&#xff0c;我们详细探讨了Pod的概念、创建、…

linux X11窗口开发

X11 控制窗口 窗口信息查询 检索窗口信息工具 xprop xprop执行后会出现一个光标&#xff0c;这个光标可以获取到窗口信息 X11 获取窗口信息&#xff0c;操作窗口 X11 遍历获取当前显示窗口的标题 _NET_WM_NAME, 置顶模拟键盘输入操作 开发依赖 apt install libX11-dev l…

【前端Vue】社交信息头条项目完整笔记第2篇:二、登录注册,准备【附代码文档】

社交媒体-信息头条项目完整开发笔记完整教程&#xff08;附代码资料&#xff09;主要内容讲述&#xff1a;一、项目初始化使用 Vue CLI 创建项目,加入 Git 版本管理,调整初始目录结构,导入图标素材,引入 Vant 组件库,移动端 REM 适配,关于 , 配置文件,封装请求模块。十、用户关…

LeetCode-1669题:合并两个链表(原创)

【题目描述】 给你两个链表 list1 和 list2 &#xff0c;它们包含的元素分别为 n 个和 m 个。请你将 list1 中下标从 a 到 b 的全部节点都删除&#xff0c;并将list2 接在被删除节点的位置。下图中蓝色边和节点展示了操作后的结果&#xff1a; 请你返回结果链表的头指针。 【…

10 - Debian如何让特定用户切换root身份

作者&#xff1a;网络傅老师 特别提示&#xff1a;未经作者允许&#xff0c;不得转载任何内容。违者必究&#xff01; Debian如何让特定用户切换root身份 《傅老师Debian小知识库系列之10》——原创 前言 傅老师Debian小知识库特点&#xff1a; 1、最小化拆解Debian实用技能…

LNMP架构之mysql数据库实战

mysql安装 到官网www.mysql.com下载源码版本 实验室使用5.7.40版本 tar xf mysql-boost-5.7.40.tar.gz #解压 cd mysql-boost-5.7.40/ yum install -y cmake gcc-c bison #安装依赖性 cmake -DCMAKE_INSTALL_PREFIX/usr/local/mysql -DMYSQL_DATADIR/data/mysql -DMYSQL_…

MySQL为什么会选错索引

在平时不知道一有没有遇到过这种情况&#xff0c;我明明创建了索引&#xff0c;但是MySQL为何不用索引呢&#xff1f;为何要进行全索引扫描呢&#xff1f; 一、对索引进行函数操作 假设现在维护了一个交易系统&#xff0c;其中交易记录表 tradelog 包含交易流水号(tradeid)、交…

【分布式计算框架】Hadoop伪分布式安装

&#x1f57a;作者&#xff1a; 主页 我的专栏C语言从0到1探秘C数据结构从0到1探秘Linux &#x1f618;欢迎 ❤️关注 &#x1f44d;点赞 &#x1f64c;收藏 ✍️留言 文章目录 Hadoop伪分布式安装一、实验目的二、实验环境三、实验内容基本任务1&#xff1a;安装Linux虚拟机(至…

[Vue3] 配置 Pinia 并存储、读取、修改数据 | 集中式状态(数据)管理

安装 npm i pinia main.ts import ./assets/main.cssimport { createApp } from vue import App from ./App.vue import { createPinia } from pinia // 引入Pinia// 创建一个应用 const app createApp(App)const pina createPinia() app.use(pina) // 挂载整个应用到app容器…

『Apisix进阶篇』动态负载均衡:APISIX的实战演练与策略应用

&#x1f680;『Apisix系列文章』探索新一代微服务体系下的API管理新范式与最佳实践 【点击此跳转】 &#x1f4e3;读完这篇文章里你能收获到 &#x1f3af; 掌握APISIX中多种负载均衡策略的原理及其适用场景。&#x1f4c8; 学习如何通过APISIX的Admin API和Dashboard进行负…

AIGC趋势下软件工程强智能编码来临了么?

一、背景 在AIGC&#xff08;AI Generated Content&#xff0c;人工智能生成内容&#xff09;的趋势下&#xff0c;软件工程领域的“强智能编码”是指通过深度学习、自然语言处理等前沿技术&#xff0c;使AI具备理解、学习、推理和生成代码的能力&#xff0c;从而实现自动化或…

操作系统:经典进程同步问题的高级探讨

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

ChatGPT提升工作生产力方法和技巧ChatGPT enhances work productivity methods and techniques

使用ChatGPT提升工作效率的一些详细步骤和技巧&#xff1a; 1. 快速撰写和编辑文档 撰写文档&#xff1a;当需要撰写报告、方案、邮件等内容时&#xff0c;可以直接向ChatGPT提出请求&#xff0c;例如&#xff1a;“请帮我写一份关于第一季度销售业绩的总结报告。”之后&#x…

Mybatis-plus + 通用mapper(tk.mybatis)

推荐课程&#xff1a;MyBatisPlus实战教程02-课程介绍与案例演示_哔哩哔哩_bilibili 官网&#xff1a;MyBatis-Plus (baomidou.com) 目录 01 引言 1&#xff09;MyBatis与MyBatis-Plus区别 2&#xff09;Mybatis-plus入门案例 案例一&#xff1a;spring容器版本的案例 案例…

将二进制数a的每一位右移b位operator.rshift(a,b)

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 将二进制数a的 每一位右移b位 operator.rshift(a,b) [太阳]选择题 请问执行operator.rshift(4, 1)的结果为&#xff1f; import operator print("【显示】二进制2&#xff1a;",bi…