leetcode刷题(剑指offer) 287.寻找重复数

287.寻找重复数

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

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

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

示例 1:

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

示例 2:

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

提示:

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

题解

本题要求是只能使用常量级的空间复杂度,由于题目中给出了条件nums中的长度有n + 1个数字,且数字只在1-n中,因此想到了建立映射关系。

首先举个例子,如果是一个没有重复数字出现的数组,3, 2, 4, 2, 1, 将n和num[n]建立映射关系。如下

0 -> 3
1 -> 2
2 -> 4
3 -> 2
4 -> 1
// 建立出来的链表结构如下
0 -> 3 -> 2 -> 4 -> 1 -> 2

可以看出,让出现具有重复的数值的时候,使用n, num[n]的映射关系,构建出来的链表会出现环,而环的入口即是重复的数字。

0
3
2
4
1

思考这题的时候,主要有以下几种情况的思考。

  1. 第一种情况,是我的解题的时候出现的问题,就是会脑补出一些不存在的情况,数组一共有n+1个成员,每个成员的取值只能在[1, n]的范围内,因此不会出现n + 1, 比如说, 一个数组长度是5,那么这个数组的成员中就不会出现5这个数字,因此不会存在,下一个指针没有指向的情况。

  2. 第二种情况,就是自成环的情况,比如说有这样的映射,存在num = {3, 1, 3, 3, 2}

    0 -> 3
    1 -> 1
    2 -> 3
    3 -> 3
    4 -> 2
    
    0
    2
    1
    3
    4

    这种情况就是出现了两个环,1和1自己成环了,不过这种不要紧,因为1自己的这个环,并不会干扰重复元素3所在环的运算,从0出发的时候不会经过1,只当1不存在就好了。

  3. 第三种情况,多个元素成首位相连的环,如num = {2, 3, 2, 1, 4}

    0 -> 2
    1 -> 3
    2 -> 2
    3 -> 1
    4 -> 4
    
    0
    2
    1
    3
    4

    这种情况,是最烧我脑的情况,因为1和3只出现了一次,而且他们也成环了,这也使得我一度怀疑这个思路对不对。但是后来画图出来,再仔细屡屡还是可以发现,我们搜环是从下标0开始的,因为题目已经明确了取值是在[1, n]范围内的,因此,当我们从0开始出发的时候,并不会遇上自成环的情况,也不会遇上首位相连的情况,因为没有任何一个元素会等于0,因此也不会形成0的首位相连环,因此还是这个思路,找到入环的第一个节点,就是重复的数,像上述的情况,1-3, 4-4的环,我们可以直接忽略他们。

    说了这么多,可以得出结论就是,这个题可以当成链表的题来做哈哈。


    那么为了方便思考,我们将情况切换回第一个例子。

    0
    3
    2
    4
    1

    如何找到链表的入环节点,这里是一个固定的套路,为什么这样子我也不知道,记得就好了。

    定义一个快指针(faster)和一个慢指针(slower)。所谓快指针就是移动的比较快的指针,比如我一开始指针在0的位置,我移动一次就可以移动到2,移动了两格,慢指针,就是移动一次就移动一格。

    如果链表种存在环的话,使用快慢指针,一直向前移动,总有一天,这两个指针,会在环上的某个节点处相遇。

    当两个指针相遇之后,再重新定义一个指针,在此我将其定义为origin,指向链表一开始的0位置,然后让这个指针和慢指针(slower)一样的移动速度移动,当这个origin和slower相遇的时候,他们相遇的节点,就是入环节点,就是这么神奇,别问我为什么。

    代码如下:

public class _287寻找重复数 {public static void main(String[] args) {int[] nums = new int[]{1, 3, 4, 2, 2};System.out.println(findDuplicate(nums));}public static int findDuplicate(int[] nums) {// 判断特殊情况if (0 == nums.length) {return 0;}// 快指针// 确定快慢指针的初始位置int start = 0;for (int i = 0; i < nums.length; i++) {start = i;if (start != slowerNext(nums, start)) {break;}}int faster = fasterNext(nums, start);int slower = slowerNext(nums, start);int origin = start;while (faster != slower) {faster = fasterNext(nums, faster);slower = slowerNext(nums, slower);}// 寻找环的出口while (origin != slower) {origin = slowerNext(nums, origin);slower = slowerNext(nums, slower);}return origin;}public static int fasterNext(int[] nums, int index) {return next(nums, index, 2);}public static int slowerNext(int[] nums, int index) {return next(nums, index, 1);}public static int next(int[] nums, int index, int steps) {if (steps == 0) {return index;}return next(nums, nums[index], steps - 1);}}

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

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

相关文章

LeetCode 46. 全排列

46. 全排列 给定一个不含重复数字的数组 nums &#xff0c;返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&#xff1a;[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]示例 2&#xff1a; 输入&#…

Ddosify 作为压测工具的使用指南

文章目录 1. 写在最前面1.1 Kubernetes 监控1.2 Performance Testing 2. 命令行安装 & 使用2.1 安装2.2 使用2.2.1 默认的例子2.2.2 定制的例子 3. Dashboard 安装 & 使用3.1 安装3.2 使用3.2.1 简单使用3.2.3 依赖的服务介绍 4. 碎碎念5. 参考资料 1. 写在最前面 由于…

Docker-Jenkins编译android-app的两种方案

Docker-Jenkins编译android-app的两种方案 android开发使用jenkins编译&#xff0c;自动集成修改点/自动命名/自动备份&#xff0c;将修改的apk发布到测试服务器发布网盘&#xff0c;而不需要用通讯工具传来传去。 jenkins用在互联网开发编译比较常见&#xff0c;如果android开…

C++ //练习 2.40 根据自己的理解写出Sales_data类,最好与书中的例子有所区别。

C Primer&#xff08;第5版&#xff09; 练习 2.40 练习 2.40 根据自己的理解写出Sales_data类&#xff0c;最好与书中的例子有所区别。 环境&#xff1a;Linux Ubuntu&#xff08;云服务器&#xff09; 工具&#xff1a;vim 代码块 struct Sales_data{std::string bookNo;…

charles mac抓包unknown问题

第一步&#xff1a;mac上安装Charles后&#xff0c;mac安装证书&#xff1a; 第二步&#xff1a;mac上信任证书 第三步&#xff1a;手机上安装证书 安装提示&#xff1a;电脑上通过help–>SSLProxying–> Install Charles Root Ceriticate on a Mobile Device or Remote …

SVN 常用命令

help —— 帮助 在使用过程中&#xff0c;可随时使用help命令查看各常用svn命令&#xff1a; svn helpcheckout —— 检出 svn checkout https://计算机名:8443/svn/仓库名/ 说明&#xff1a; 1、可缩写为&#xff1a; svn co https://计算机名:8443/svn/仓库名/ 2、844…

kubeadm 安装k8s集群后,master节点notready问题解决方案

使用kubeadm 安装k8s集群后&#xff0c;加载calico cni 网络组件后&#xff0c;master节点notready问题 表现为&#xff1a; 使用命令查看日志&#xff1a;journalctl -f -u kubelet 报错如下&#xff1a; Failed to start ContainerManager failed to initialize top level…

2024-01-22(MongoDB)

1.Mongodb使用的业务场景&#xff1a; 传统的关系型数据库/mysql在“三高”需求以及应对web2.0的网站需求面前&#xff0c;有点力不从心&#xff0c;什么是“三高”需求&#xff1a; a. 对数据库高并发的读写需求 b. 对海量数据的高效率存储和访问需求 c. 对数据库的高可扩…

实现VLAN之间的路由

原理&#xff1a;路由器子接口 一个接口允许多个VLAN通过&#xff08;避免占用物理路由器接口&#xff09;。 目标 第 1 部分&#xff1a;单臂路由 第 2 部分&#xff1a;配置第三层交换机的路由端口 第 3 部分&#xff1a;带SVI的VLAN间路由 第 4 部分&#xff1a;补充知…

苹果笔记本MacBook电脑怎么卸载软件?三种方法快速卸载软件

苹果笔记本MacBook电脑是一款非常流行的电脑&#xff0c;但是有时候我们可能需要卸载一些不需要的软件。下面是一些简单的步骤&#xff0c;可以帮助您在MacBook电脑上卸载软件。 苹果笔记本MacBook电脑怎么卸载软件&#xff1f;三种实用方法快速卸载软件&#xff01; 方法一&a…

【网络安全 -> 防御与保护】信息安全概述

目录 一、信息安全现状及挑战 二、信息安全脆弱性及常见安全攻击 1、网络环境的开放性 2、协议栈的脆弱性及常见攻击 3、操作系统的脆弱性及常见攻击 4、终端的脆弱性及常见攻击 5、其他常见攻击 三、信息安全要素 四、整体安全解决方案 一、信息安全现状及挑战 &…

【5G 接口协议】N2接口协议NGAP(NG Application Protocol)介绍

博主未授权任何人或组织机构转载博主任何原创文章&#xff0c;感谢各位对原创的支持&#xff01; 博主链接 本人就职于国际知名终端厂商&#xff0c;负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作&#xff0c;目前牵头6G算力网络技术标准研究。 博客…

图神经网络X项目|基于图神经网络的电商行为的预测(5%)

文章目录 Jupyter Notebook 学习人工智能的好帮手数据集数据集下载数据集调用数据集应用技巧——获取不重复的编号数据集应用技巧——随机采样数据集应用技巧——抽取前N项进行模拟测试 数据集构建技巧一——查看数据集构建进度 Jupyter Notebook 学习人工智能的好帮手 【Jupy…

(delphi11最新学习资料) Object Pascal 学习笔记---第3章第一节(简单语句与复合语句)

Object Pascal 学习笔记&#xff0c;Delphi 11 编程语言的完整介绍 作者: Marco Cantu 笔记&#xff1a;豆豆爸 3.1 简单语句与复合语句 ​ 编程指令通常称为语句。一个程序块可以由多个语句组成。有两种类型的语句&#xff0c;简单语句和复合语句。当语句不包含任何其他子语…

【XR806开发板试用】系列之一 - Linux环境下Ubuntu完全开发流程

前言 为了让极术社区开发者体验搭载安谋科技STAR-MC1处理器的面向IoT领域的全志XR806开发板&#xff0c;极术社区联合全志在线开发者社区共同推出XR806开发板免费试用活动。 极术社区特准备了200块XR806开发板作为2022年社区新年活动&#xff0c;申请的人数有600多&#xff0c…

Tensorflow2.0笔记 - tensor的合并和分割

主要记录concat,stack,unstack和split相关操作的作用 import tensorflow as tf import numpy as nptf.__version__#concat对某个维度进行连接 #假设下面的tensor0和tensor1分别表示4个班级35名同学的8门成绩和两个班级35个同学8门成绩 tensor0 tf.ones([4,35,8]) tensor1 tf…

SPN的重要性 | 保障服务安全和身份验证

什么是 Service Principal Name&#xff08;SPN&#xff09;&#xff1f; SPN 是用于标识网络服务的唯一名称。在 Windows 中&#xff0c;SPN 与 Kerberos 认证一起使用。 SPN 是由两部分组成的&#xff1a; 服务类型&#xff08;Service Class&#xff09;&#xff1a; 表示…

RK3399平台开发系列讲解(网络篇)什么是Linux路由

🚀返回专栏总目录 文章目录 一、什么是路由二、路由配置命令沉淀、分享、成长,让自己和他人都能有所收获!😄 一、什么是路由 一张路由表中会有多条路由规则。每一条规则至少包含这三项信息。 目的网络:这个包想去哪儿?出口设备:将包从哪个口扔出去?下一跳网关:下一个…

vscode显示函数列表插件 - AZ AL Dev Tools/AL Code Outline

官网&#xff1a; AZ AL Dev Tools/AL Code Outline - Visual Studio Marketplace 适用于 Visual Studio Code 的 AZ AL 开发工具/AL 代码大纲 此扩展最初被命名为“AL 代码大纲”&#xff0c;因为它最初是 AL 代码大纲面板&#xff0c;从中可以在 AL 语法节点上运行不同的代码…

js对象数组去重封装

1.简单的数组去重就使用常用的去重方式好了 可以看这里&#xff1a; js多种数组去重方法-CSDN博客 2. 下面是关于object的数组去重 // 普通数组和 Object数组去重 const list1 [1, 4, 45, 6, 3, 4, 5, 3, 2, 1, 3, 2]; const list2 ["sss", "sss", &q…