( 数组和矩阵) 287. 寻找重复数 ——【Leetcode每日一题】

news2024/11/18 9:19:24

❓287. 寻找重复数

难度:中等

给定一个包含 n + 1 个整数的数组 nums ,其数字都在 [1, n] 范围内(包括 1n),可知至少存在一个重复的整数。

假设 nums 只有 一个重复的整数 ,返回 这个重复的数

你设计的解决方案必须 不修改 数组 nums 且只用常量级 O ( 1 ) O(1) O(1) 的额外空间。

示例 1:

输入:nums = [1,3,4,2,2]
输出:2

示例 2:

输入:nums = [3,1,3,4,2]
输出:3

提示:

  • 1 < = n < = 1 0 5 1 <= n <= 10^5 1<=n<=105
  • nums.length == n + 1
  • 1 <= nums[i] <= n
  • nums 中 只有一个整数 出现 两次或多次 ,其余整数均只出现 一次

进阶:

  • 如何证明 nums 中至少存在一个重复的数字?
  • 你可以设计一个线性级时间复杂度 O ( n ) O(n) O(n) 的解决方案吗?

💡思路:

法一:二分查找

由于数组中存储的数的范围是[1,n]且是连续的,所以我们可以进行二分查找,遍历数组统计小于等于数组中整数范围的中点mid的个数cnt

  • 如果cnt > mid则重复的数一定在mid左边;
  • 否则一定在mid的右边。
  • 然后区间对半缩小,直到l > h时,l 即为重复的数。

法二:快慢指针

  • 类似于有环链表中找出环的入口:

我们对 nums 数组建图,每个位置 i 连一条 i → nums[i]的边。由于存在的重复的数字 target,因此 target这个位置一定有起码两条指向它的边,因此整张图一定存在环,且我们要找到的 target 就是这个环的入口

对示例1进行建图,如下:

在这里插入图片描述
有两条边指向22即是环的入口,也是我们要找的target:

  • 我们先设置慢指针 slow 和快指针 fast ,慢指针每次走一步,快指针每次走两步,根据「Floyd 判圈算法」两个指针在有环的情况下一定会相遇;
  • 此时我们再将 slow放置起点 0,两个指针每次同时移动一步相遇的点就是答案

这里简单证明为什么后面将 slow 放置起点后移动相遇的点就一定是答案了。
假设环长为L,从起点到环的入口的步数是 a,从环的入口继续走 b 步到达相遇位置,从相遇位置继续走 c 步回到环的入口,则有b+c= L,其中Labc都是正整数。

根据上述定义,慢指针走了a+b步,快指针走了2(a+b)步。从另一个角度考虑,在相遇位置,快指针比慢指针多走了若干圈,因此快指针走的步数还可以表示成a+b+kL,其中 k 表示快指针在环上走的圈数。联立等式,可以得到:
2 ( a + b ) = a + b + k L 2(a+b)=a+b+kL 2(a+b)=a+b+kL
解得 a = kL − b,整理可得:
a = ( k − 1 ) L + ( L − b ) = ( k − 1 ) L + c a=(k−1)L+(L−b)=(k−1)L+c a=(k1)L+(Lb)=(k1)L+c
从上述等式可知,如果慢指针从起点出发,快指针从相遇位置出发,每次两个指针都移动一步,则慢指针走了 a 步之后到达环的入口,快指针在环里走了 k−1 圈之后又走了 c 步,由于从相遇位置继续走 c 步即可回到环的入口,因此快指针也到达环的入口。两个指针在环的入口相遇,相遇点就是答案。

🍁代码:(Java、C++)

法一:二分查找

Java

class Solution {
    public int findDuplicate(int[] nums) {
        int l = 1, h = nums.length - 1;
        while(l <= h){
            int mid = l + (h - l) / 2;
            int cnt = 0;
            for(int num : nums){
                if(num <= mid){
                    cnt++;
                }
            }
            if(cnt > mid) h = mid - 1;
            else l = mid + 1;
        }
        return l;
    }
}

C++

class Solution {
public:
    int findDuplicate(vector<int>& nums) {
        int l = 1, h = nums.size() - 1;
        while(l <= h){
            int mid = l + (h - l) / 2;
            int cnt = 0;
            for(int num : nums){
                if(num <= mid){
                    cnt++;
                }
            }
            if(cnt > mid) h = mid - 1;
            else l = mid + 1;
        }
        return l;
    }
};

法二:快慢指针

Java

class Solution {
    public int findDuplicate(int[] nums) {
        int slow = nums[0], fast = nums[nums[0]];
        while(slow != fast){
            slow = nums[slow];
            fast = nums[nums[fast]];
        }
        slow = 0;
        while(slow != fast){
            slow = nums[slow];
            fast = nums[fast];
        }
        return slow;
    }
}

C++

class Solution {
public:
    int findDuplicate(vector<int>& nums) {
        int slow = nums[0], fast = nums[nums[0]];
        while(slow != fast){
            slow = nums[slow];
            fast = nums[nums[fast]];
        }
        slow = 0;
        while(slow != fast){
            slow = nums[slow];
            fast = nums[fast];
        }
        return slow;
    }
};

🚀 运行结果:

在这里插入图片描述

🕔 复杂度分析:

  • 时间复杂度 O ( n ) O(n) O(n),其中 n n u m s nums nums 数组的长度,「Floyd 判圈算法」时间复杂度为线性的时间复杂度;二分查找时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn), 二分查找最多需要二分 O ( l o g ⁡ n ) O(log⁡n) O(logn)
  • 空间复杂度 O ( 1 ) O(1) O(1),我们只需要常数空间存放若干变量。

题目来源:力扣。

放弃一件事很容易,每天能坚持一件事一定很酷,一起每日一题吧!
关注我 leetCode专栏,每日更新!

注: 如有不足,欢迎指正!

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

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

相关文章

基于樽海鞘算法的极限学习机(ELM)回归预测-附代码

基于樽海鞘算法的极限学习机(ELM)回归预测 文章目录 基于樽海鞘算法的极限学习机(ELM)回归预测1.极限学习机原理概述2.ELM学习算法3.回归问题数据处理4.基于樽海鞘算法优化的ELM5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;本文利用樽海鞘算法对极限学习机进行优化&…

TouchGFX界面开发 | 使用STM32CubeMX移植TouchGFX

本文基于STM32F429IGT6 RGB (800 * 480)硬件平台&#xff0c;详细记录了如何利用STM32CubeMX将TouchGFX移植到STM32F429IGT6&#xff0c;并驱动RGB屏幕。相关软件的安装&#xff0c;可参考TouchGFX软件安装一文 TouchGFX的应用框架如下图所示&#xff1a; 一、STM32CubeMX配…

JoJo‘s Incredible Adventures

题目&#xff1a; 题意解析&#xff1a; 这个题目是要求找出输入的字符串&#xff0c;&#xff0c;字符串的循环移位s由k右边是字符串Sn−k1...Sn&#xff0c;S1&#xff0c;S2...Sn−k。直到所有的字符&#xff0c;都循坏出现在字符串的开头&#xff0c;然后输入1形成的长方形…

MySQL之Adaptive Hash Index详解

前言 本文已收录在MySQL性能优化原理实战专栏&#xff0c;点击此处浏览更多优质内容。 目录 一、MySQL InnoDB是否支持哈希索引&#xff1f;1.1 InnoDB不支持Hash Index1.2 InnoDB支持Hash Index 二、Adaptive Hash Index的概念三、涉及Adaptive Hash Index的参数3.1 innodb_ad…

接口优化的策略

1.批处理 批量思想&#xff1a;批量操作数据库&#xff0c;这个很好理解&#xff0c;我们在循环插入场景的接口中&#xff0c;可以在批处理执行完成后一次性插入或更新数据库&#xff0c;避免多次IO。 //批量入库 batchInsert();List的安全操作有以下几种方式&#xff1a; 使…

DAY 50 LVS负载均衡器 NAT模式

群集概述 群集的含义 Cluster&#xff0c;集群、群集由多台主机构成&#xff0c;但对外只表现为一一个整体&#xff0c;只提供一-个访问入口(域名或IP地址)&#xff0c; 相当于一台大型计算机。 为什么使用群集 互联网应用中&#xff0c;随着站点对硬件性能、响应速度、服务…

Python学习日记(2)

有关数字类型&#xff0c;字符串&#xff0c;函数 目录 有关数字类型&#xff0c;字符串&#xff0c;函数 数字 字符串 索引操作 切片操作 单个字符编码 运算符 还有一些常用的内置函数 Python输入函数 输出函数print()语法 python的函数也能给默认值 Python是个脚…

C++系列一: C++简介

C入门简介 1. C语言的特点2. C编译器3. 第一个 C 程序4. 总结&#xff08;手稿版&#xff09; C 是一种高级编程语言&#xff0c;是C语言的扩展和改进版本&#xff0c;由Bjarne Stroustrup于1983年在贝尔实验室为了支持C语言中的面向对象编程而创建。C 既能够进行底层的系统编程…

全注解下的SpringIoc 续4-条件装配bean

Spring Boot默认启动时会加载bean&#xff0c;如果加载失败&#xff0c;则应用就会启动失败。但是部分场景下&#xff0c;我们希望某个bean只有满足一定的条件下&#xff0c;才允许Spring Boot加载&#xff0c;所以&#xff0c;这里就需要使用Conditional注解来协助我们达到这样…

二叉搜索树(BST)详解

文章目录 性质二叉搜索树的遍历遍历伪代码实现 二叉搜索树的查找伪代码实现 二叉搜索树最大元素伪代码实现 二叉搜索树最小元素伪代码实现 二叉搜索树的插入伪代码实现 二叉搜索树的删除删除叶子节点&#xff08;对应上面第一种情况&#xff09;&#xff1a;删除度为1的节点&am…

机械硬盘(HDD)与固态硬盘(SSD)

目录 机械硬盘&#xff08;HDD&#xff09; 最小组成单元是扇区 硬盘结构 硬盘工作原理 硬盘上的数据组织 硬盘指标 影响性能的因素 固态硬盘&#xff08;SSD&#xff09; 最小存储单元是Cell SSD的特点 SSD架构 NAND Flash 闪存介质 地址映射管理 FTL闪存转换层 机械硬盘&…

Python之模块和包(九)

1、模块 1、模块概述 模块是一个包含了定义的函数和变量等的文件。模块可以被程序引入&#xff0c;以使用该模块中的函数等功能。通俗讲&#xff1a;模块就好比是工具包&#xff0c;要想使用这个工具包中的工具(就好比函数)&#xff0c;就需要导入这个模块。 2、import 在P…

Redis分布式锁原理之实现秒杀抢优惠卷业务

Redis分布式锁原理之实现秒杀抢优惠卷业务 1. 实现秒杀下单2. 库存超卖问题分析2.1 乐观锁解决超卖问题 3. 优惠券秒杀-一人一单3.1 集群环境下的并发问题 4、分布式锁4.1 基本原理和实现方式对比4.2 Redis分布式锁的实现核心思路4.3 实现分布式锁版本一4.4 Redis分布式锁误删情…

【Java入门合集】第三章面向对象编程(上)

【Java入门合集】第三章面向对象编程&#xff08;上&#xff09; 博主&#xff1a;命运之光 专栏&#xff1a;JAVA入门 理解面向对象三大主要特征&#xff1b; 掌握类与对象的区别与使用&#xff1b; 掌握类中构造方法以及构造方法重载的概念及使用&#xff1b; 掌握包的定义、…

国民技术N32G430开发笔记(14)-IAP升级 usart2接收数据

IAP升级 Usart2接收数据 1、之前有一节我们将PA6 PA7复用成了usart2的功能&#xff0c;这一节我们用usart2接收来自树莓派的升级请求&#xff0c;然后完成N32G430的Iap升级。 2、接线 PA9 PA10 接usb转串口模块A&#xff0c;A模块插入电脑。 PA6 PA7 接usb转串口模块B&#xf…

【移动端网页布局】流式布局案例 ⑥ ( 多排按钮导航栏 | 设置浮动及宽度 | 设置图片样式 | 设置文本 )

文章目录 一、多排按钮导航栏样式及核心要点1、实现效果2、总体布局设计3、设置浮动及宽度4、设置图片样式5、设置文本 二、完整代码实例1、HTML 标签结构2、CSS 样式3、展示效果 一、多排按钮导航栏样式及核心要点 1、实现效果 要实现下面的导航栏效果 ; 2、总体布局设计 该导…

计算机网络笔记:DNS域名解析过程

基本概念 DNS是域名系统&#xff08;Domain Name System&#xff09;的缩写&#xff0c;也是TCP/IP网络中的一个协议。在Internet上域名与IP地址之间是一一对应的&#xff0c;域名虽然便于人们记忆&#xff0c;但计算机之间只能互相认识IP地址&#xff0c;域名和IP地址之间的转…

基于探路者算法的极限学习机(ELM)回归预测-附代码

基于探路者算法的极限学习机(ELM)回归预测 文章目录 基于探路者算法的极限学习机(ELM)回归预测1.极限学习机原理概述2.ELM学习算法3.回归问题数据处理4.基于探路者算法优化的ELM5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;本文利用探路者算法对极限学习机进行优化&…

算法 DAY45 动态规划07 70. 爬楼梯 322. 零钱兑换 279. 完全平方数 139. 单词拆分 多重背包

70. 爬楼梯 和377. 组合总和 Ⅳ (opens new window)基本就是一道题了。本题代码不长&#xff0c;题目也很普通&#xff0c;但稍稍一进阶就可以考察完全背包 class Solution { public:int climbStairs(int n) {vector<int> nums {1,2};vector<int> dp(n1,0);dp[0…

while语句和until语句顺便带点小实验

while语句和until语句 一、while用法二、Until循环语句三、趣味小实验猜价格的游戏&#xff08;价格是随机数&#xff09;写一个计算器脚本闲来无事去购物 一、while用法 for循环语句非常适用于列表对象无规律&#xff0c;且列表来源以固定&#xff08;如某个列表文件&#xf…