【LeetCode】剑指 Offer 03. 数组中重复的数字 -- Java Version

news2025/1/25 8:57:40

题目链接: https://leetcode.cn/problems/shu-zu-zhong-zhong-fu-de-shu-zi-lcof/

1. 题目介绍(03. 数组中重复的数字)

找出数组中重复的数字。

在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字

【测试用例】:
示例 1:

输入:
[2, 3, 1, 0, 2, 5, 3]
输出:2 或 3

【条件约束】:

2 <= n <= 100000

2. 题解

2.1 给输入的数组排序 – 差:O(nlogn)

class Solution {
    public int findRepeatNumber(int[] nums) {
        // 1. 给nums数组排序 
        Arrays.sort(nums);
        // 2. 遍历打印nums,检查是否排序成功
        // for (int j = 0; j < nums.length; j++) {
        //     System.out.print(nums[j] + "\t");
        // }
		// 3. 冒泡判重
        for (int j = 0; j < nums.length-1; j++) {
           if(nums[j] == nums[j+1]){
               return nums[j];
           }
        }
        return -1;
    }
}

在这里插入图片描述

2.2 哈希表判重 – 中:O(n)


class Solution {
    /**
     * 时间复杂度:O(n)
     * 空间复杂度:O(n)
     */
    public int findRepeatNumber(int[] nums) {
        // 1. 创建一个哈希表 
        HashMap<Integer,Integer> map = new HashMap<>();
        // 2. 遍历nums数组,并进行相同key判断
        for (int i = 0; i < nums.length; i++){
            // 3. 如果重复,则返回重复值,并对当前重复key中的value+1
            if (map.containsKey(nums[i])){
                map.replace(nums[i],map.get(nums[i])+1);
                return nums[i];
            }else{
            // 4. 如果不重复,就将其记录在map中
                map.put(nums[i],1);
            }
        }
        // 5. 循环结束,无重复结果,返回-1
        return -1;
    }
}

在这里插入图片描述

2.3 下标顺序排列交换 – 优:O(n)

class Solution {
    /**
     * 时间复杂度:O(n)
     * 空间复杂度:O(1)
     */
    public int findRepeatNumber(int[] nums) {
        // 1. 判空判断 
        if (nums.length <= 0) return -1;
        // 2. 错误值判断
        for (int i = 0; i < nums.length; i++){
            if (nums[i] < 0 || nums[i] > nums.length-1){
                return -1;
            }
        }
        // 3. 数组元素与下标位置排列交换
        for (int i = 0; i < nums.length; i++){
            while (nums[i] != i){
                // 4. 如果当前数组元素不等于当前下标,那么先判断当前元素是否属于重复,
                //    即已经有一个正确的值处于了正确的位置
                if (nums[i] == nums[nums[i]]){
                    return nums[i];
                }
                // 5. 交换nums[i]与nums[nums[i]]
                int temp = nums[i];
                nums[i] = nums[temp];
                nums[temp] = temp;
            }
        }
        // 4. 循环结束,说明数组中无重复元素
        return -1;
    }
}

在这里插入图片描述

3. 思考

按理说这里的哈希表判重方法应该会比给输入的数组排序的耗时短才对,但是这里的哈希表判重耗时却达到了8ms,当然不排除测试用例的偶然情况,回头可以再测试测试。

4.扩展题 – 不修改数组找出重复的数字

4.1 辅助数组+对应下标位置排列

/**
 * 时间复杂度为O(n)
 * 空间复杂度为O(n)
 */
public class Duplicate2 {
    /**
     * @param intArray    输入数组
     * @param duplicaiton 将首次找到的重复数字利用duplicaiton[0] = ?存入数组
     * @return 如果输入数组无效返回false,duplicaiton[0]=-1
     */
    public static boolean findDuplicate(int[] intArray, int[] duplicaiton) {
        // 杜绝数组为空
        if (intArray.length == 0) {
            duplicaiton[0] = -1;
            return false;
        }
        // 杜绝数组有非法数字
        for (int i = 0; i < intArray.length; i++) {
            if (intArray[i] < 1 || intArray[i] > intArray.length - 1) {
                duplicaiton[0] = -1;
                return false;
            }
        }
        int start = 1;
        int end = intArray.length - 1;

        while (end >= start) {
            // >> 右移一位相当于除以2
            int middle = ((end + start) >> 1);
            int count = countRange(intArray, start, middle);
            // 终止条件
            if (start == end) {
                if (count > 1) {
                    duplicaiton[0] = middle;
                    return true;
                } else {
                    break;
                }
            }
            if (count > (middle - start) + 1) {
                end = middle;
            } else {
                start = middle + 1;
            }

        }
        duplicaiton[0] = -1;
        return false;

    }

    /**
     * @param intArray 输入数组
     * @param start    区间起始数字
     * @param end      区间结束数字
     * @return 个数
     * @Description 统计数组在区间里数字的个数
     */
    public static int countRange(int[] intArray, int start, int end) {
        if (intArray.length == 0) {
            return 0;
        }
        int count = 0;
        for (int i : intArray) {
            if (i >= start && i <= end) {
                count++;
            }
        }
        return count;
    }

4.2 二分思想 + 限制区间

/**
 * 时间复杂度为O(nlogn)
 * 空间复杂度为O(1)
 */
public class BinarySearch {
    /**
     * 使用递归的二分查找
     *
     * @param arr 有序数组
     * @param key 待查找关键字
     * @return 找到的位置
     */
    public static int recursionBinarySearch(int[] arr, int key, int low, int high) {
        if (arr.length == 0) {
            return -1;
        }
        if (key < arr[low] || key > arr[high] || low > high) {
            return -1;
        }
        int middle = (high - low) >> 2;
        if (arr[middle] > key) {
            //比关键字大则关键字在左区域
            return recursionBinarySearch(arr, key, low, middle - 1);
        } else if (arr[middle] < key) {
            //比关键字小则关键字在右区域
            return recursionBinarySearch(arr, key, middle + 1, high);
        } else {
            return middle;
        }
    }

    /**
     * 不使用递归的二分查找
     * @param arr
     * @param key
     * @return 关键字位置
     */
    public static int commonBinarySearch(int[] arr, int key) {
        int low = 0;
        int high = arr.length - 1;

        if (key < arr[low] || key > arr[high] || low > high) {
            return -1;
        }

        while (low <= high) {
            int middle = (low + high) >> 2;
            if (arr[middle] > key) {
                //比关键字大则关键字在左区域
                high = middle - 1;
            } else if (arr[middle] < key) {
                //比关键字小则关键字在右区域
                low = middle + 1;
            } else {
                return middle;
            }
        }

        return -1;
    }

}

5. 参考资料

[1] 剑指Offer系列(java版,详细解析) 03. 数组中重复的数字 (扩展题代码来源)

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

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

相关文章

linux篇【15】:应用层-网络https协议

目录 一.HTTPS介绍 1.HTTPS 定义 2.HTTP与HTTPS &#xff08;1&#xff09;端口不同&#xff0c;是两套服务 &#xff08;2&#xff09;HTTP效率更高&#xff0c;HTTPS更安全 3.加密&#xff0c;解密&#xff0c;密钥 概念 4.为什么要加密&#xff1f; 5.常见的加密方式…

TransE及其实现

TransE 该模型将关系和实体表示为同一空间中的向量&#xff0c;给定事实&#xff08;h,r,s&#xff09;&#xff08;h,r,s&#xff09;&#xff08;h,r,s&#xff09;关系 rrr 的向量 rrr被解释为头实体向量 hhh与尾实体向量 ttt之间的平移,因此嵌入实体hhh和ttt可以通过平移向…

分享82个HTML电子产品模板,总有一款适合您

分享82个HTML电子产品模板&#xff0c;总有一款适合您 82个HTML电子产品模板下载链接&#xff1a;https://pan.baidu.com/s/106NtZkrVefSFGGS54xk-kA?pwdbvn8 提取码&#xff1a;bvn8 Python采集代码下载链接&#xff1a;采集代码.zip - 蓝奏云 import os import shutil …

TongWeb8防止System.exit代码导致的进程停止

现象&#xff1a;当应用中存在System.exit 、Runtime.exit代码执行时&#xff0c;会导致TongWeb进程停止&#xff0c;从而产生如下日志&#xff1a;2023-02-14 09:47:36 [WARN] - The web application [webtest01] is still processing a request that has yet to finish. This…

LeetCode 19.删除链表的倒数第 N 个结点

原题链接 难度&#xff1a;middle\color{orange}{middle}middle 题目描述 给你一个链表&#xff0c;删除链表的倒数第 nnn 个结点&#xff0c;并且返回链表的头结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5]示例 2&#x…

快速部署个人导航页:美好的一天从井然有序开始

很多人都习惯使用浏览器自带的收藏夹来管理自己的书签&#xff0c;然而收藏夹存在着一些问题。 经过长时间的累积&#xff0c;一些高频使用的重要网站和偶尔信手收藏的链接混在了一起&#xff0c;收藏夹因为内容过多而显得杂乱无章&#xff1b;收藏夹没有什么美观可言&#xf…

【java】Spring Boot --40 个 Spring Boot 常用注解(建议收藏)

本文目录一、Spring Web MVC 注解Spring Web MVC 注解RequestMappingRequestBodyGetMappingPostMappingPutMappingDeleteMappingPatchMappingControllerAdviceResponseBodyExceptionHandlerResponseStatusPathVariableRequestParamControllerRestControllerModelAttributeCross…

sqlServer 2019 开发版(Developer)下载及安装

下载软件 官网只有2022的&#xff0c;2019使用百度网盘进行下载 安装下崽器 选择自定义安装 选择语言、以及安装位置 点击“安装” 安装 SQL Server 可能的故障 以上步骤安装后会弹出以上界面&#xff0c;如果未弹出&#xff0c;手动去安装目录下点击 SETUP.EXE 文件…

数据分析与SAS学习笔记1

数据分析的六层模型&#xff1a; 1&#xff09;数据源层&#xff1a;数据分析的数据源&#xff1b;DBA&#xff1b;初加工&#xff1b;对数据源按某些规则进行抽取&#xff0c;ETL&#xff1b; 2&#xff09;数据仓库层&#xff1a;OLAP的功能&#xff0c;联机事务处理。OLTP、…

这才叫装机必备 , 这4款电脑软件超级实用,用一次就爱上

好用又免费的软件犹如被掩盖的珍珠&#xff0c;一旦发现了&#xff0c;让你满眼欣喜。 1、HiBit Uninstaller 这是一款大小不到10M的超实用卸载软件&#xff0c;完全免费无任何广告&#xff0c;兼顾垃圾清理、流氓软件卸载等超多实用功能&#xff0c;流氓软件卸载能力比某安全卫…

T-SQL基础(SQL高级编程语言)(二)

一、常量、变量 1. 常量 又称为字面值或标量值,程序运行过程中值不变’O’Bbaar’&#xff0c;如果单引号中的字符串包含引号&#xff0c;可以使用两个单引号表示嵌入的单引号。 2.变量 ​ 变量名不能与系统变量相同://img- 变量的声明赋值与使用 case※※ ​ case语句上…

实例一:MATLAB APP design- 简单的函数表达式运算(Y=X1^3+X2^2+X3)

一、APP 界面设计展示注&#xff1a;在自变量框输入自变量&#xff0c;点击计算按钮&#xff0c;结果就会显示在因变量输出框。二、APP设计界面运行结果展示该APP界面设计包括表达式运算显示框&#xff0c;自变量输入框&#xff0c;计算按钮&#xff0c;因变量输出框。注&#…

正大数据抢先看 祝各位情人节快乐

美国1月消费者物价指数 (CPI)周二 21:30&#xff0c;估6.2%&#xff0c;前值 6.5%。 周三12:00达拉斯FED总裁、03:00纽约FED总裁发表演说、和欧洲 央行 (ECB)总裁拉加德22:00演说。 日本政府预定周二向国会提出日本银行 (央行&#xff0c;BOJ) 总裁黑田东彦的继任人选。 市场高…

【服务器数据恢复】Hyper-V虚拟机数据恢复案例

服务器数据恢复环境&#xff1a; WinServer操作系统服务器&#xff0c;部署Hyper-V虚拟机环境&#xff1b; 虚拟机的硬盘文件和配置文件存储在一台存储设备中&#xff1b; 该存储设备配置&#xff1a;一组4盘raid5阵列存放虚拟机数据单块盘存放虚拟机数据备份。 服务器故障&am…

附录1-pytorch目标检测

源码来自作者Bubbliiiing&#xff0c;我对参考链接的代码略有修改&#xff0c;网盘地址 链接&#xff1a;百度网盘 请输入提取码 提取码&#xff1a;bfvs 目录 1 参考 2 环境 3 数据集准备 3.1 VOCdevkit/VOC2007 3.2 model_data/voc_classes.txt 3.3 voc_annota…

【Java|多线程与高并发】进程与线程的区别与联系

文章目录什么是进程什么是线程上下文切换多线程一定比串行执行快吗进程与线程的区别与联系什么是进程 进程的定义:进程是正在运行的程序实体&#xff0c;并且包括这个运行的程序中占据的所有系统资源&#xff0c;比如说CPU&#xff08;寄存器&#xff09;&#xff0c;IO,内存&a…

自学前端最容易犯的10个的错误,入门学前端快来看看

在前端学习过程中&#xff0c;有很多常见的误区&#xff0c;包括过度关注框架和库、缺乏实践、忽视算法和数据结构、忽视浏览器兼容性、缺乏团队合作经验、忽视可访问性、重构次数过多、没有关注性能、缺乏设计知识以及没有持续学习等。要避免这些误区&#xff0c;应该注重基础…

Lambda表达式详细操作

一、基础语法 形态一&#xff1a;匿名内部类 Runnable runnable new Runnable() {Overridepublic void run() {System.out.println(Thread.currentThread().getName());} };runnable.run();形态二&#xff1a;完整的Lambda表达式 口诀&#xff1a;复制小括号&#xff0c;写…

消息中间件----内存数据库 Redis7(第1章 Redis 概述)

第1章 Redis 概述1.1 Redis 简介Redis&#xff0c;Remote Dictionary Server&#xff0c;远程字典服务&#xff0c;由意大利人 Salvatore Sanfilippo&#xff08;又名Antirez&#xff09;开发&#xff0c;是一个使用 ANSI C 语言编写、支持网络、可基于内存亦可持久化的日志型、…

【路径规划】基于Dijkstra算法及Floyd算法的通信与网络路径规划(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…