540. 有序数组中的单一元素(中等)

540. 有序数组中的单一元素

  • 1. 题目描述
  • 2.详细题解
  • 3.代码实现
    • 3.1 Python
    • 3.2 Java

1. 题目描述

题目中转:540. 有序数组中的单一元素

在这里插入图片描述

2.详细题解

    方法一:若不限定时间复杂度,则扫描遍历一遍即可找到仅出现一次的数,具体实现见Python实现方法一。
   方法二:若不限定空间复杂度,借助集合实现,具体实现见Python实现方法二,基本原理为:对数组求集合,再对集合中所有数字的和乘以2,结果假定为 X X X,此时 X X X的结果包括所有出现两次的数字之和,且对单独出现的数字也计算了两次,再对数组求和结果假定为 Y Y Y X − Y X-Y XY的差值即为单独出现的数字。
   方法三——二分查找(根据子区间个数奇偶):限定的时间复杂度: O ( l o g n ) O(log n) O(logn),空间复杂度: O ( 1 ) O(1) O(1)的情况下,结合数组有序,此时可以利用二分查找算法进行查找,但需要变型。数组中除了一个元素仅出现一次,其它元素均出现两次,因此数组的总长度为奇数,二分查找时的中位数恰好将数组等分,且一分为二后的左右区间的元素个数相同,元素个数可能为偶数或奇数。

  • 对于偶数个数:此时中位数与左元素或者右元素谁相等,则单独元素则在那个区间;否则中位数即为单独出现的数字。【为什么呢?原理在于,一分为二后,左区间或右区间元素个数为偶数,如果不含单独的数字,则该区间的元素都是成双出现,不会出现与中位数相等的情况】
  • 对于奇数个数:此时中位数与左元素或者右元素谁相等,则单独元素则不在那个区间,否则中位数即为单独出现的数字。【为什么呢?原理在于,一分为二后,左区间或右区间元素个数为奇数,如果不含单独的数字,则该区间的元素加上中位数正好均成双出现】
      具体算法如下:
  • Step1:初始化:两个指针 l e f t left left r i g h t right right,分别指向数组的起始和结束位置;
  • Step2:计算中间元素的索引: m i d = ( l e f t + r i g h t ) / 2 mid = (left + right) / 2 mid=(left+right)/2
  • Step3:如果 n u m s [ m i d ] = = n u m s [ m i d − 1 ] nums[mid] == nums[mid-1] nums[mid]==nums[mid1]:
  •   如果nums[mid] >= nums[left]的值,说明左区间有序;
  •   否则右区间有序;
  • Step4:如果 n u m s [ m i d ] = = n u m s [ m i d + 1 ] nums[mid] == nums[mid+1] nums[mid]==nums[mid+1](同理):
  •   如果目标值在左区间内,则更新 r i g h t = m i d − 1 right=mid-1 right=mid1
  •   否则在右区间内,则更新 l e f t = m i d + 1 left = mid + 1 left=mid+1;
  • Step5:否则 m i d mid mid元素即为单独出现的数字,返回即可:
  • Step6:当指针 l e f t left left小于 r i g h t right right时,重复步骤Step2_Step6;
  • Step7:否则循环结束返回 n u m s [ l e f t ] nums[left] nums[left]

  该算法具体实现见Python实现方法三。
   方法四——二分查找(根据成双元素出现在单独数字的左右侧而下标奇偶性不同查找):对于数组中单独出现数字之前成双出对的元素来说,其索引下标均为先偶数再奇数,而单独出现数字后成双出对的元素来说,其索引下标均为先奇数再偶数,那么则可以利用该性质使用二分查找算法,对于 m i d mid mid判断其奇偶性,结合其是与前一个元素相等或者与后一个元素相等,从而判断单独出现的数字在那个区间。【具体的,当 m i d mid mid为偶数且与 m i d + 1 mid+1 mid+1元素相等(或 m i d mid mid为奇数且与前一个元素 m i d − 1 mid-1 mid1元素相等),则单独出现的数字在右区间,否则在左区间;< m i d mid mid为偶数时与加1判断,奇数时与减1判断,可使用异或统一计算】
  具体算法如下:

  • Step1:初始化:两个指针 l e f t left left r i g h t right right,分别指向数组的起始和结束位置;
  • Step2:计算中间元素的索引: m i d = ( l e f t + r i g h t ) / 2 mid = (left + right) / 2 mid=(left+right)/2
  • Step3:如果 n u m s [ m i d ] = n u m s [ m i d 异或 1 ] nums[mid] = nums[mid异或1] nums[mid]=nums[mid异或1]
  •    n u m s [ m i d ] = n u m s [ m i d 异或 1 ] nums[mid] = nums[mid异或1] nums[mid]=nums[mid异或1]成立,说明 m i d mid mid在单独出现数字的左侧,故单独出现数字在右区间,更新 l e f t = m i d + 1 left=mid+1 left=mid+1
  • Step4:否则,说明 m i d mid mid在单独出现数字的右侧,故单独出现数字在左区间,更新 r i g h t = m i d right=mid right=mid
  • Step5:当指针 l e f t left left小于 r i g h t right right时,重复步骤Step2_Step5;
  • Step6:否则循环结束返回 n u m s [ l e f t ] nums[left] nums[left]

  该算法具体实现见Python实现方法四。
   方法五——二分查找(根据单独出现数字的索引奇偶性判断):对于数组中单独出现的数字,其它元素均成双出现,故单独出现数字的索引肯定为偶数,若下标为 x x x,则 n u m s [ x ] ! = n u m s [ x + 1 ] nums[x]!=nums[x+1] nums[x]!=nums[x+1],故可利用此性质进行二分查找,查找最小的 x x x即为单独出现的数字;具体的,在偶数索引的下标范围内进行查找。
  具体算法如下:

  • Step1:初始化:两个指针 l e f t left left r i g h t right right,分别指向数组的起始和最后一个偶数索引,由于数字长度为奇数,因此最后一个偶数索引即为数组的结束位置;
  • Step2:计算中间元素的索引: m i d = ( l e f t + r i g h t ) / 2 mid = (left + right) / 2 mid=(left+right)/2
  • Step3:如果 m i d mid mid为奇数,则 m i d = m i d − 1 mid=mid-1 mid=mid1,确保 m i d mid mid为偶数:
  •   如果 n u m s [ m i d ] = n u m s [ m i d + 1 ] nums[mid] = nums[mid+1] nums[mid]=nums[mid+1]成立,说明 m i d mid mid在单独出现数字的左侧,故单独出现数字在右区间,更新 l e f t = m i d + 2 left=mid+2 left=mid+2
  •   如果 n u m s [ m i d ] = n u m s [ m i d + 1 ] nums[mid] = nums[mid+1] nums[mid]=nums[mid+1]不成立,故单独出现数字在左区间,更新 r i g h t = m i d right=mid right=mid
  • Step4:否则,说明 m i d mid mid在单独出现数字的右侧,故单独出现数字在左区间,此时 m i d mid mid可能为单独出现的数字,因此更新 r i g h t = m i d right=mid right=mid
  • Step5:当指针 l e f t left left小于 r i g h t right right时,重复步骤Step2_Step5;
  • Step6:否则循环结束返回 n u m s [ l e f t ] nums[left] nums[left]

  该算法具体实现见Python实现方法五和Java实现。

3.代码实现

  对于上述五个方法,除最后一个方法,前四个方法仅Python实现。

3.1 Python

方法一:遍历

class Solution:
    def singleNonDuplicate(self, nums: List[int]) -> int:
        n = len(nums)
        for i in range(0, n, 2):
            if i != n - 1:
                if nums[i] != nums[i+1]:
                    return nums[i]
                else:
                    continue
            else:
                return nums[i]

在这里插入图片描述
方法二:集合

class Solution:
    def singleNonDuplicate(self, nums: List[int]) -> int:
        return sum(set(nums)) * 2 - sum(nums)

在这里插入图片描述
方法三:二分查找(1)

class Solution:
    def singleNonDuplicate(self, nums: List[int]) -> int:
        left, right = 0, len(nums) - 1
        while left < right:
            mid = (left + right) // 2
            if nums[mid] != nums[mid-1] and nums[mid] != nums[mid+1]:
                return nums[mid]
            elif nums[mid] == nums[mid-1]:
                if (mid - left) % 2 == 0:
                    right = mid
                else:
                    left = mid + 1
            else:
                if (mid - left) % 2 == 0:
                    left = mid
                else:
                    right = mid - 1
        return nums[left]

在这里插入图片描述
方法四:二分查找(2)

class Solution:
    def singleNonDuplicate(self, nums: List[int]) -> int:
        left, right = 0, len(nums) - 1
        while left < right:
            mid = (left + right) // 2
            if nums[mid] == nums[mid ^ 1]:
                # 如果mid为偶数,则mid与1的异或为mid+1
                # 如果mid为奇数,则mid与1的异或为mid-1
                left = mid + 1
            else:
                right = mid
        return nums[left]

在这里插入图片描述

方法五:二分查找(3)

class Solution:
    def singleNonDuplicate(self, nums: List[int]) -> int:
        left, right = 0, len(nums) - 1
        while left < right:
            mid = (left + right) // 2
            mid = mid if mid % 2 == 0 else mid - 1  # 也可以使用与运算统一
            # mid -= mid & 1,当mid为偶数时,mid&1=0;当mid为奇数时,mid&1=1
            if (nums[mid] != nums[mid+1]):
                right = mid
            else:
                left = mid + 2
        return nums[left]

在这里插入图片描述

3.2 Java

class Solution {
    public int singleNonDuplicate(int[] nums) {
        int left = 0, right = nums.length - 1;
        while (left < right){
            int mid = (left +right) / 2;
            mid -= mid & 1;
            if (nums[mid] != nums[mid+1]){
                right = mid;
            }else{left = mid + 2;}
        }
        return nums[left];
    }
}

在这里插入图片描述

  执行用时不必过于纠结,对比可以发现,对于python和java完全相同的编写,java的时间一般是优于python的;至于编写的代码的执行用时击败多少对手,执行用时和网络环境、当前提交代码人数等均有关系,可以尝试完全相同的代码多次执行用时也不是完全相同,只要确保自己代码的算法时间复杂度满足相应要求即可,也可以通过点击分布图查看其它coder的code。

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

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

相关文章

Maven Archetype 自定义项目模板:高效开发的最佳实践

文章目录 前言一、Maven Archetype二、创建自定义 Maven Archetype三、定制 Archetype 模板四、手动创建 Archetype 模板项目五、FAQ5.1 如何删除自定义的模板5.2 是否可以在模板中使用空文件夹 六、小结推荐阅读 前言 在软件开发中&#xff0c;标准化和快速初始化项目结构能够…

什么是JSON ,ajax和json关系

一. JSON 1 JSON概述 JavaScript对象文本表示形式&#xff08;JavaScript Object Notation : js对象简写) json是js对象 json是目前 前后端数据交互的主要格式之一 * java对象表示形式User user new User();user.setUsername("后羿");user.setAge(23);user.setSex…

开发国际短剧系统的策略解析

一、明确项目目标和需求 1、功能需求&#xff1a;确定系统应具备的基本功能&#xff0c;如用户注册、登录、浏览短剧、评论、分享、个性化推荐等。 2、性能需求&#xff1a;确保系统能够承受高并发访问&#xff0c;保证视频流畅播放&#xff0c;减少卡顿和延迟。 3、跨文化传播…

中序遍历的两种实现——二叉树专题复习

递归实现&#xff1a; /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val val; }* TreeNode(int val, TreeNode left, TreeNode right)…

【算法】(C语言):堆排序

堆&#xff08;二叉树的应用&#xff09;&#xff1a; 完全二叉树。最大堆&#xff1a;每个节点比子树所有节点的数值都大&#xff0c;根节点是最大值。父子索引号关系&#xff08;根节点为0&#xff09;&#xff1a;&#xff08;向上&#xff09;子节点x&#xff0c;父节点(x…

命令行升级ubuntu版本过程中出现的grub问题 解决

1、问题描述 使用命令行升级ubuntu18到20版本后&#xff0c;系统提示重启&#xff0c;使用reboot命令重启后&#xff0c;不显示服务器ip&#xff0c;或是显示但无法ssh远程连接服务器了&#xff0c;使用屏幕连接服务器后发现出现grub问题。 2、问题经过 命令行输入如下升级u…

【虚拟机】虚拟机网络无法访问问题【已解决】

【虚拟机】虚拟机无法上网问题【已解决】 问题探究解决方法法1&#xff1a;查看相关“网络服务”是否处于正常启动状态法2&#xff1a;重启网络法3&#xff1a;重新安装VMWare法4&#xff1a;使用NAT模式&#xff0c;每次打开win7都没连上网的解决办法 问题探究 安装了很多个虚…

Objection 对命令的批量操作

假定现在需要对好多不同的类进行批量hook&#xff0c;逐个hook非常繁琐&#xff0c;那么可以要将这些hook的类放到一个文件里&#xff0c;并且在这些类的前面加上hook命令&#xff0c;内容如下 使用如下命令执行该文件中的命令 objection -g 测试 explore -c d:/hookData/toHoo…

如何从腾讯云迁移到AWS

随着跨境出海潮不断扩大&#xff0c;企业越来越意识到将工作负载迁移到海外节点的必要性&#xff0c;以获取更多功能、灵活性和性能。然而&#xff0c;顺利迁移业务主机并确保业务稳定访问是一项具有挑战性的任务。在此挑战中&#xff0c;借助AWS迁移工具和迁移流程的强大支持&…

docker 安装 禅道

docker pull hub.zentao.net/app/zentao:20.1.1 sudo docker network create --subnet172.172.172.0/24 zentaonet 使用 8087端口号访问 使用禅道mysql 映射到3307 sudo docker run \ --name zentao2 \ -p 8087:80 \ -p 3307:3306 \ --networkzentaonet \ --ip 172.172.172.…

WIN32核心编程 - 进程操作(一) 进程基础 - 创建进程 - 进程句柄

公开视频 -> 链接点击跳转公开课程博客首页 -> 链接点击跳转博客主页 目录 进程基础 进程的定义与概念 进程的组成 创建进程 可执行文件 CreateProces 执行流程 GetStartupInfo 进程终止 进程句柄 创建进程 打开进程 进程提权 内核模拟 回溯对象 自身进…

有哪些好用的eHR人事系统?国内外HR软件选型指南分享

在人力资源管理信息化这个问题上&#xff0c;不同行业的企业对人力资源管理软件的需求侧重点不一样&#xff0c;并且通常企业规模决定了企业需求的强烈程度&#xff0c;以及能花在这个软件采购上的预算。 首先需要对公司需要人力资源软件的目的和基本需求加以明确。你为什么想用…

软件测试必问必背面试题

01 软件测试理论部分 1.1 测试概念 1. 请你分别介绍一下单元测试、集成测试、系统测试、验收测试、回归测试 单元测试&#xff1a;完成最小的软件设计单元&#xff08;模块&#xff09;的验证工作&#xff0c;目标是确保模块被正确的编码集成测试&#xff1a;通过测试发现与…

【Linux】探索网络编程:TCP/UDP协议解析与Socket应用实例

文章目录 前言&#xff1a;1. 预备知识1.1 理解源IP地址和目的IP地址1.2 认识端口号1.3 理解"端口号"和"进程ID"1.4 理解源端口号和目的端口号1.5 认识TCP协议1.6 认识UDP协议1.6 TCP vs UDP 可靠性1.7 网络字节序 2. socket 编程接口2.1 socket 常见API2.…

为了SourceInsight从Linux回到Windows

什么是SourceInsight 现在上网搜索这个软件&#xff0c;大多数说他是一个代码阅读软件&#xff1b;但是在官方的说法里面&#xff0c;这是一款支持多语言的编辑器。大概长这样&#xff1a; 看起来十分老旧是吧&#xff0c;但是他其实他已经是第四代了哈哈哈。其实这个软件是我…

LeetCode 全排列

思路&#xff1a;这是一道暴力搜索问题&#xff0c;我们需要列出答案的所有可能组合。 题目给我们一个数组&#xff0c;我们很容易想到的做法是将数组中的元素进行排列&#xff0c;如何区分已选中和未选中的元素&#xff0c;容易想到的是建立一个标记数组&#xff0c;已经选中的…

开发电商ERP系统需要接入哪些平台API?

跟随全渠道发展趋势&#xff0c;很多实体商家开设电商店铺&#xff0c;为消费者提供便捷的购物体验&#xff0c;增强消费者的满意度&#xff0c;同时也提升了企业自身的市场竞争力。为了满足商家业务拓展需求&#xff0c;很多原本主要服务于实体商贸企业的ERP服务商&#xff0c…

vim快捷键 提高工作效率

目录 1. :set nu 显示行号 :set nonu 取消显示行号 2. End 快速移动光标到行尾 3. Home 快速移动光标到行首 4. 10G 快速移动光标到第10行 5. G 快速到文件的底部 6. 1G 快速到第一行 &#xff08;gg&#xff09; 7. …

[Mysql] 的基础知识和sql 语句.教你速成(下)——数据库的约束篇

目录 前言 约束 一.我们为什么需要约束 二.常见的约束类型 NOT NULL 约束 UNIQUE 约束 DEFAULT 约束 PRIMARY KEY FOREIGN KEY CHECK约束 原因&#xff1a; 结尾 前言 距离上篇的更新已经快两周了,这个时候大伙都已经考完了吧!现在更新多少有点马后炮,但是没办法呀…

Kubernetes基于helm安装 harbor

Kubernetes基于helm安装 harbor 之前harbor的安装都是借助docker完成一键安装部署&#xff0c;安装完成之后harbor组件均运行到一台机器上面&#xff0c;本文实践harbor在k8s环境中的部署。 准备工作 根据harbor官方要求&#xff1a; Kubernetes cluster 1.20Helm v3.2.0 …