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

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.mfbz.cn/a/495020.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

算法之美:二叉树演进之多叉树及B-Tree树原理

在上篇文章我们了解了平衡二叉树的优势&#xff0c;了解到平衡二叉树能够对不平衡的节点施加旋转&#xff0c;使得树达趋于平衡&#xff0c;以提升查询效率&#xff0c;操作效率很高&#xff0c;与之同时也存在着不少的问题&#xff0c;例如我们在实际使用中会通常会将树加载到…

RiPro主题-子主题huzao-child美化包v4.0带更新,附下载插件

压缩包里包含子主题下载插件演示数据 V4.0更新内容如下 1、左下角会员推广广告悬浮集成到后台 2、底部悬浮登录增加是否登录判断 3、在线申请友链页面美化 4、手机端底部版权信息被遮挡优化 5、部分bug修复及细节优化 源码下载 RiPro主题-子主题huzao-child美化包v4.0带…

Matlab|基于隐式Zbus高斯法的三相不平衡潮流计算【可设定变压器数量和位置】【Yy、Yd两种绕组方式】

目录 主要内容 部分代码 结果一览 主要内容 该模型基于隐式高斯法实现对配电网的三相不平衡潮流计算&#xff0c;通过选项可实现【不含变压器】和【含变压器】两种方式下的潮流计算&#xff0c;并且通过参数设置可实现多个变压器接入&#xff0c;该程序可计算【IE…

SSH连接SFTP传输:如何使用libssh库在Linux环境下进行(文件、文件夹)传输到远端服务器

建立SSH会话并连接远端服务器SSH身份验证密码验证密钥验证生成密钥查看密钥拷贝密钥验证密钥是否正确 SFTP子系统构建传输普通文件递归传输文件夹完整传输小demo 建立SSH会话并连接远端服务器 target_host&#xff1a;远端主机IPtarget_username&#xff1a;远端主机用户名 s…

Echarts之x轴,Y轴配置项大全

ECharts是一个强大的数据可视化库&#xff0c;提供了丰富的配置项来定制图表的x轴和y轴。下面是ECharts中x轴和y轴的配置项大全&#xff1a; xAxis配置项&#xff1a; type&#xff1a;轴类型&#xff0c;可选值有&#xff1a;“value”&#xff08;数值轴&#xff09;, “cat…

生产调度问题分类——机器视角

获取更多资讯&#xff0c;赶快关注上面的公众号吧&#xff01; 文章目录 单机调度并行机调度流水车间调度作业车间调度柔性作业车间开放车间总结 生产调度问题是实际工作中广泛存在的运筹学问题&#xff0c;可以描述为“给定若干加工任务&#xff0c;根据已有的生产条件&#…

ubuntu之搭建samba文件服务器

1. 在服务器端安装samba程序 sudo apt-get install samba sudo apt-get install smbclient 2.配置samba服务 sudo gedit /etc/samba/smb.conf 在文件末尾追加入以下配置 [develop_share] valid users ancy path /home/ancy public yes writable y…

Tuxera for Mac2024免费读写硬盘U盘工具

作为软件产品专家&#xff0c;我对各类软件都有较为深入的了解&#xff0c;下面介绍Tuxera for Mac这款读写硬盘/U盘工具的相关信息&#xff1a; Tuxera for Mac是一款高效稳定的NTFS读写工具&#xff0c;专为解决Mac系统无法直接读写NTFS格式驱动器的问题而设计。它提供了完整…

直接插入排序 希尔排序 选择排序 堆排序

目录 一. 排序的概念及应用 1.1 排序的概念 1.2 常见的排序算法 二. 常见排序算法的实现(从小到大排序) 2.1 插入排序 2.1.1基本思想&#xff1a; 2.1.2 直接插入排序 2.1.3 希尔排序( 缩小增量排序) 2.2 选择排序 2.2.1基本思想&#xff1a; 2.2.2 直接选择排序: 2…

保障校园网络安全用堡垒机的几个原因分析

校园&#xff0c;人人都熟悉的地方&#xff0c;梦想知识开始的地方。在互联网数字化快速发展的今天&#xff0c;网络安全的学习环境是非常必要的。所以采购保障校园网络安全工具是必要的。那为什么一定要用堡垒机呢&#xff1f;这里我们一起来简单分析一下原因。 保障校园网络…

iOS - Runtime-消息机制-objc_msgSend()

iOS - Runtime-消息机制-objc_msgSend() 前言 本章主要介绍消息机制-objc_msgSend的执行流程&#xff0c;分为消息发送、动态方法解析、消息转发三个阶段&#xff0c;每个阶段可以做什么。还介绍了super的本质是什么&#xff0c;如何调用的 1. objc_msgSend执行流程 OC中的…

OceanBase中NOT EXISTS是否需要被改写

作者简介 张瑞远&#xff0c;曾经从事银行、证券数仓设计、开发、优化类工作&#xff0c;现主要从事电信级IT系统及数据库的规划设计、架构设计、运维实施、运维服务、故障处理、性能优化等工作。 持有Orale OCM,MySQL OCP及国产代表数据库认证。 获得的专业技能与认证包括 Oce…

安卓玩机工具推荐----MTK芯片读写分区 备份分区 恢复分区 制作线刷包 从0开始 工具操作解析【三】

同类博文; 安卓玩机工具推荐----MTK芯片读写分区 备份分区 恢复分区 制作线刷包 工具操作解析 安卓玩机工具推荐----MTK芯片读写分区 备份分区 恢复分区 制作线刷包 工具操作解析【二】-CSDN博客 回顾以往 在以前的博文简单介绍了这款工具的rom制作全程。今天针对这款工具的…

Rust 02.控制、引用、切片Slice

1.控制流 //rust通过所有权机制来管理内存&#xff0c;编译器在编译就会根据所有权规则对内存的使用进行 //堆和栈 //编译的时候数据的类型大小是固定的&#xff0c;就是分配在栈上的 //编译的时候数据类型大小不固定&#xff0c;就是分配堆上的 fn main() {let x: i32 1;{le…

YoloV5改进策略:Neck和Head改进|ECA-Net:用于深度卷积神经网络的高效通道注意力|多种改进方法|附结构图

摘要 本文使用ECA-Net注意力机制加入到YoloV5Neck和Head中。我尝试了多种改进方法&#xff0c;并附上改进结果&#xff0c;方便大家了解改进后的效果&#xff0c;为论文改进提供思路。&#xff08;改进中。。。。&#xff09; 论文&#xff1a;《ECA-Net&#xff1a;用于深度…

Android中运动事件的处理

1.目录 目录 1.目录 2.前言 3.程序演示 4.第二种程序示例 5.扩展 2.前言 触摸屏&#xff08;TouchScreen&#xff09;和滚动球&#xff08;TrackBall&#xff09;是 Android 中除了键盘之外的主要输入设备。如果需要使用触摸屏和滚动球&#xff0c;主要可以通过使用运动事…

ruoyi-nbcio-plus基于vue3的flowable的流程条件的升级修改

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a;RuoYi-Nbcio后台管理系统 http://122.227.135.243:9666/ 更多nbcio-boot功能请看演示系统 gitee源代码地址 后端代码&#xff1a…

JavaScript中的继承方式详解

Question JavaScript实现继承的方式&#xff1f; 包含原型链继承、构造函数继承、组合继承、原型式继承、寄生式继承、寄生组合式继承和ES6 类继承 JavaScript实现继承的方式 在JavaScript中&#xff0c;实现继承的方式多种多样&#xff0c;每种方式都有其优势和适用场景。以下…

HarmonyOS(鸿蒙开发)入门篇

如果需要学习鸿蒙开发可以查看以下学习资源链接 OpenAtom OpenHarmony Develop applications - HUAWEI HarmonyOS APP 转载请注明出处HarmonyOS(鸿蒙开发&#xff09;入门篇-CSDN博客&#xff0c;谢谢&#xff01;

unity 数据的可视化

【Unity 实用插件篇】| 可视化图表插件XCharts (折线图、柱状图、饼图等)详细教学-腾讯云开发者社区-腾讯云 Package https://github.com/XCharts-Team/XCharts/releases 官方文档案例 入门教程&#xff1a;5分钟上手 XCharts 3.0 | XCharts (xcharts-team.github.io)
最新文章