【算法题】数组系列(找出数组中重复的数字、二维数组中的查找)

news2024/11/25 22:36:41

算法题 数组系列

  • 一、找出数组中重复的数字
    • 1.1、题目
    • 1.2、解题思路1(排序法)
    • 1.3、解题思路2(hash)
    • 1.4、小结
  • 二、二维数组中的查找
    • 2.1、题目
    • 2.2、理解题目
    • 2.3、解题思路
      • 2.3.1、暴力枚举
      • 2.3.2、二分查找
      • 2.3.3、对角线查询(Z型)
    • 2.4、小结
  • 总结

一、找出数组中重复的数字

1.1、题目

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

示例 1:

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

来源:力扣(LeetCode)。

1.2、解题思路1(排序法)

将数字排序,排序后的数字如果前一个元素和后一个元素相同(nums[i]==nums[i+1]),则就是一个重复数字。

class Solution {
public:
    int findRepeatNumber(vector<int>& nums) {
        int n=nums.size()-1;
        sort(nums.begin(),nums.end());
        while(n)
        {
            if(nums[n]==nums[n-1])
                return nums[n];
            n--;
        }
        return 0;

    }
};

时间复杂度:O(n)。

空间复杂度:O(n)。不重复的每个元素都可能存入集合,因此占用 O(n)额外空间。

1.3、解题思路2(hash)

利用unordered_map来检查重复的数字。将数组的元素填入unordered_map<int,bool>,通过检查bool来判定重复的数字。

class Solution {
public:
    int findRepeatNumber(vector<int>& nums) {
        unordered_map<int, bool> map;
        for(int num:nums)
        {
            if(map[num])
                return num;
            map[num]=true;
        }
        return -1;

    }
};

执行用时:44 ms, 在所有 C++ 提交中击败了38.00%的用户
内存消耗:26.8 MB, 在所有 C++ 提交中击败了42.25%的用户

时间复杂度 O(N)。

空间复杂度 O(N)。

1.4、小结

排序法是比较容易想到的算法,核心是先排序再比较。hash方式也比较常用。

二、二维数组中的查找

2.1、题目

在一个 n * m 的二维数组中,每一行都按照从左到右 非递减 的顺序排序,每一列都按照从上到下 非递减 的顺序排序。请完成一个高效的函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

示例:

现有矩阵 matrix 如下:
[
[1, 4, 7, 11, 15],
[2, 5, 8, 12, 19],
[3, 6, 9, 16, 22],
[10, 13, 14, 17, 24],
[18, 21, 23, 26, 30]
]
给定 target = 5,返回 true。
给定 target = 20,返回 false。

来源:力扣(LeetCode)

2.2、理解题目

二维数组中,从左到右是依次递增排序,从上到下是依次递增排序;给定一个数字,判断该数组中是否存在该数字。
在这里插入图片描述

2.3、解题思路

2.3.1、暴力枚举

暴力枚举:直接遍历整个矩阵matrix,判断target是否出现即可。

class Solution {
public:
    bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) {
        int n=matrix.size();
        if(n==0)
            return false;
        int m=matrix[0].size();
        if(m==0)
            return false;
        if(target<matrix[0][0] || target>matrix[n-1][m-1])
            return false;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                if(matrix[i][j]>target)
                    break;
                else if(matrix[i][j]==target)
                    return true;
                
            }
        }
        return false;

    }
};

时间复杂度:O(nm)。
空间复杂度:O(1)。

2.3.2、二分查找

C++ STL标准库中还提供有 lower_bound()、upper_bound()、equal_range() 以及 binary_search() 这 4 个查找函数,它们的底层实现采用的都是二分查找的方式。

这里采用lower_bound()函数,在指定区域内查找不小于目标值的第一个元素。

class Solution {
public:
    bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) {
        for(const auto &m:matrix)
        {
            auto it= lower_bound(m.begin(),m.end(),target);
            if(it!=m.end() && *it==target)
                return true;
        }
        return false;

    }
};

时间复杂度: O(n log m)。

空间复杂度:O(1)。

2.3.3、对角线查询(Z型)

从二维数组的右上角[0,m]开始遍历,在每一步的遍历中,假设位置处于[x,y],就以matrix的左下角为左下角,[x,y]为右上角进行搜索,即行范围为x ~ m-1,列范围为0 ~ y。

如果matrix[x][y] == target,返回true。
如果matrix[x][y]>target,因为行是递增的,列也是递增的,那么y列的所有数都大于target,将y减一来缩小范围。
如果matrix[x][y]<target,因为行是递增的,列也是递增的,x加1来缩小范围。

class Solution {
public:
    bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) {
        int n=matrix.size();
        if(n==0)
            return false;
        int m=matrix[0].size();
        if(m==0)
            return false;
        
        int x=0,y=m-1;
        while(x<n && y>=0)
        {
            if(matrix[x][y]==target)
                return true;
            else if(matrix[x][y]>target)
                y--;
            else
                x++;
        }

        return false;

    }
};

时间复杂度:O(n+m)。

空间复杂度:O(1)。

优化:

class Solution {
public:
    bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) {
        int n = matrix.size() - 1, m = 0;
        while(n >= 0 && m < matrix[0].size())
        {
            if(matrix[n][m] > target) n--;
            else if(matrix[n][m] < target) m++;
            else return true;
        }
        return false;
    }
};

2.4、小结

暴力枚举属于下下策,优先考虑使用对角线搜索(或称为z型搜索)。对角线搜索类似二叉树搜索数的遍历,将二维数组旋转45°,对于每个元素,其左分支元素更小、右分支元素更大。因此,通过从 “根节点” 开始搜索,遇到比 target 大的元素就向左,反之向右,即可找到目标值 target。
在这里插入图片描述

总结

一定要做好总结,特别是当没有解出题来,没有思路的时候,一定要通过结束阶段的总结来反思犯了什么错误。解出来了也一定要总结题目的特点,题目中哪些要素是解出该题的关键。不做总结的话,花掉的时间所得到的收获通常只有 50% 左右。

在题目完成后,要特别注意总结此题最后是归纳到哪种类型中,它在这种类型中的独特之处是什么。
在这里插入图片描述

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

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

相关文章

【数据结构与算法C++实现】3、排序算法

原视频为左程云的B站教学 以下所有的swap()函数&#xff0c;函数定义为 void swap(int& a, int& b) {int t a;a b;b t; } // 也可以用异或&#xff0c;但不能传入同一个变量&#xff0c;可以是不同变量相同值 void swap(int& a, int& b) {a a ^ b;b a ^ …

极智开发 | 让wsl2读取宿主机usb设备

欢迎关注我的公众号 [极智视界]&#xff0c;获取我的更多经验分享 大家好&#xff0c;我是极智视界&#xff0c;本文介绍一下 让wsl2读取宿主机usb设备的方法。 邀您加入我的知识星球「极智视界」&#xff0c;星球内有超多好玩的项目实战源码下载&#xff0c;链接&#xff1a;…

高效处理消息:使用Spring Boot实现消息重试机制

当涉及到消息发送和接收的可靠性&#xff0c;Spring Boot提供了一些机制来确保消息的可靠传递。其中包括消息确认机制和重试机制。下面是一个示例代码&#xff0c;演示如何在Spring Boot中实现可靠的消息发送和接收。 首先&#xff0c;我们需要配置RabbitMQ的连接信息和相关属性…

58 KVM工具使用指南-应用 LibcarePlus 热补丁

文章目录 58 KVM工具使用指南-应用 LibcarePlus 热补丁58.1 前期准备58.2 加载热补丁58.3 查询补丁58.4 卸载热补丁 58 KVM工具使用指南-应用 LibcarePlus 热补丁 本节以原文件 foo.c 和补丁文件 bar.c 为例&#xff0c;介绍 LibcarePlus 热补丁的应用指导。 58.1 前期准备 …

小小面试题之赛马问题

各家大厂面试时都喜欢出一些逻辑题&#xff0c;简单的考验一下应试者的逻辑思维能力。 题目是&#xff1a;现在有64匹赛马和8条赛道&#xff0c;最少需要多少轮比赛才能选出最快的4匹马。 依据现实情况来说&#xff0c;这个问题很好回答。需要经过小组赛&#xff0c;16强赛&am…

王道操作系统学习笔记(2)——进程管理

前言 本文介绍了操作系统中的进程管理&#xff0c;文章中的内容来自B站王道考研操作系统课程&#xff0c;想要完整学习的可以到B站官方看完整版。 二&#xff1a;进程管理 2.1.1&#xff1a;进程的概念、组成、特征 程序&#xff1a;是静态的&#xff0c;就是存放在磁盘里的…

【好书精读】网络是怎样连接的 —— UDP 协议的收发操作

&#xff08; 该图由我使用 AI 绘制 &#xff09; 目录 不需要重发的数据用 UDP 发送更高效 控制用的短数据 音频和视频数据 不需要重发的数据用 UDP 发送更高效 DNS 服务器查询 IP 地址的时候我们用的是 UDP 协议 简单的说就是&#xff0c;TCP之所以复杂&#xff0c;是…

3-css高级特效-1

01-平面转换 简介 作用&#xff1a;为元素添加动态效果&#xff0c;一般与过渡配合使用 概念&#xff1a;改变盒子在平面内的形态&#xff08;位移、旋转、缩放、倾斜&#xff09; 平面转换也叫 2D 转换&#xff0c;属性是 transform 平移 transform: translate(X轴移动距…

Jetpack Compose 入门难点解疑

作者&#xff1a;晴天小庭 近些年声明式布局开发方式逐渐从网页端延展到了手机端&#xff0c;说到底还是声明式太香了&#xff0c;其代码更加清晰、简洁&#xff0c;并且更接近于自然语言的表达方式。这使得代码易于理解和维护&#xff0c;降低了开发人员的心智负担。 谷歌和苹…

【c语言12】字符串函数(strlen,strcmp,strcpy,strcat,strstr,strtok,strerror)

文章目录 一、字符串函数1.1strlen&#xff08;求字符串长度&#xff09;1.2strcmp&#xff08;比较字符串&#xff09;1.3strcpy&#xff08;拷贝字符串&#xff09;1.4strcat&#xff08;追加字符串&#xff09;1.5strstr&#xff08;判断子串&#xff09;1.6sttok&#xff0…

【C/C++】使用类和对象 封装链表

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;c系列专栏&#xff1a;C/C零基础到精通 &#x1f525; 给大…

SpringMVC全套详解

1、SpringMVC是什么1.1、MVC定义1.2、MVC和 SpringMVC的关系2.创建SpringMVC项目 2.1、SpringMVC 链接2.2、RequestMapping 注解说明2.3 、 GetMapping 和 PostMapping 3、获取参数3.1、传递单个参数3.2、传递多个参数/表单参数传递3.3、传递对象3.4、后端参数重命名(后端参数映…

C语言笔记-1

文章目录 C 基础语法注意 C 其他知识点编译过程编译器数据模型区别32/64位机器中&#xff0c;各数据类型所占位数assert() 断言&#xff08;宏&#xff09;用法总结与注意事项 C 基础语法 注意 if(a表达式) 判断的就是a的值&#xff0c;而不是判断这个赋值操作的成功与否。 查…

老天如果给我一次重来的机会,我还会选测试

在我们选择测试这行前&#xff0c;想象总是美好&#xff0c;然而现实无比扎心。 在办公环境上 想象中&#xff1a;美女&#xff08;帅哥&#xff09;环绕&#xff0c;前卫时尚&#xff0c;拥有独立办公间&#xff0c;没事转转座椅&#xff0c;偶尔来点咖啡和音乐。 现实中&…

【数据结构与算法C++实现】2、二分查找

原视频为左程云的B站教学 1 在有序数组中查找特定元素 基本思想是通过比较中间元素与目标元素的大小关系&#xff0c;将查找范围缩小一半&#xff0c;直到找到目标元素或查找范围为空为止。 时间复杂度O(logN) 因为比如说数组个数为N16, 最差的情况要分 4 次 ( [ 8 ∣ 8 ] →…

变化太快的Roop项目(版本1.0.1)

文章目录 &#xff08;一&#xff09;版本1.0.1的变化&#xff08;1.1&#xff09;项目依赖&#xff08;1.2&#xff09;模型位置&#xff08;1.3&#xff09;命令行&#xff08;1.4&#xff09;界面UI&#xff08;1.5&#xff09;处理与结果 最早的&#x1f517;接触和介绍&am…

带三维重建和还原功能的医学影像管理系统(pacs)源码

一、概述 它集影像存储服务器、影像诊断工作站及RIS报告系统于一体,主要由图像处理模块、影像数据管理模块、RIS报告模块、光盘存档模块、DICOM通讯模块、胶片打印输出等模块组成&#xff0c; 具有完善的影像数据库管理功能&#xff0c;强大的图像后处理功能&#xff08;三维重…

2-css-3

一 选择器 1 结构伪类选择器 作用&#xff1a;根据元素的结构关系查找元素。 选择器说明E:first-child查找第一个E元素E:last-child查找最后一个E元素E:nth-child(N)查找第N个E元素&#xff08;第一个元素N值为1&#xff09; li:first-child {background-color: green; }2 :…

AgilePLM应用周期性崩溃-问题解决

​ 问题现象 每周六2点左右&#xff0c;AgilePLM应用进程都会崩溃&#xff0c;具体表现为登录Agile应用服务器之后&#xff0c;找不到weblogic应用进程&#xff08;ps -ef | grep java&#xff09;。从服务器所有相关日志中没有找到任何可疑的异常日志。 当天Agile应用重启之…

UDS通信服务解析

InputOutputControlByIdentifier (0x2F)----通过ID对输入输出进行控制 2F的03子功能是"暂时接管控制权" ReadDataByIdentifier(0x2A)—通过ID读取数据或特定器件状态 ClearDiagnosticInformation(0x14)—清除故障诊断信息 UDS规定用FF FF FF表示所有种类的DTC Rou…