力扣刷题(代码回忆录)——数组部分

news2025/7/28 7:57:35

数组

  1. 数组过于简单,但你该了解这些!
  2. 数组:二分查找
  3. 数组:移除元素
  4. 数组:序数组的平方
  5. 数组:长度最小的子数组
  6. 数组:螺旋矩阵II
  7. 数组:总结篇

 704. 二分查找

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1
示例 1:

输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4

示例 2:

输入: nums = [-1,0,3,5,9,12], target = 2
输出: -1
解释: 2 不存在 nums 中因此返回 -1

提示:

  1. 你可以假设 nums 中的所有元素是不重复的。
  2. n 将在 [1, 10000]之间。
  3. nums 的每个元素都将在 [-9999, 9999]之间。

算法思路: 二分查找模板

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left = 0;
        int right = nums.size() - 1; // 定义target在左闭右闭的区间里,[left, right]
        while (left <= right) { // 当left==right,区间[left, right]依然有效,所以用 <=
            int middle = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2
            if (nums[middle] > target) {
                right = middle - 1; // target 在左区间,所以[left, middle - 1]
            } else if (nums[middle] < target) {
                left = middle + 1; // target 在右区间,所以[middle + 1, right]
            } else { // nums[middle] == target
                return middle; // 数组中找到目标值,直接返回下标
            }
        }
        // 未找到目标值
        return -1;
    }
};

 实现代码:

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

类似的二分查找的题目: 

类似题目1:35. 搜索插入位置

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

请必须使用时间复杂度为 O(log n) 的算法。

示例 1:

输入: nums = [1,3,5,6], target = 5
输出: 2

示例 2:

输入: nums = [1,3,5,6], target = 2
输出: 1

示例 3:

输入: nums = [1,3,5,6], target = 7
输出: 4

提示:

  • 1 <= nums.length <= 104
  • -104 <= nums[i] <= 104
  • nums 为 无重复元素 的 升序 排列数组
  • -104 <= target <= 104

 实现代码:

注意:左指针left指向最小大于target的值(也叫target右侧最靠近的值),右指针right会指向最大小于target的值(也叫target左侧最靠近的值)。

class Solution:
    def searchInsert(self, nums: List[int], target: int) -> int:
        left, right = 0, len(nums)-1
        while(left <= right):
            mid = int((left + right) / 2)
            if(nums[mid] == target):
                return mid
            elif(nums[mid] > target):
                right = mid - 1#右指针会指向最大小于target的值
            else:
                left = mid + 1#左指针指向最小大于target的值
        return left 

类似题目2 :34. 在排序数组中查找元素的第一个和最后一个位置(题目很新)

给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。

如果数组中不存在目标值 target,返回 [-1, -1]

你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。

示例 1:

输入:nums = [5,7,7,8,8,10], target = 8
输出:[3,4]

示例 2:

输入:nums = [5,7,7,8,8,10], target = 6
输出:[-1,-1]

示例 3:

输入:nums = [], target = 0
输出:[-1,-1]

提示:

  • 0 <= nums.length <= 105
  • -109 <= nums[i] <= 109
  • nums 是一个非递减数组
  • -109 <= target <= 109

算法分析:

寻找target在数组里的左右边界,有如下三种情况:

  • 情况一:target 在数组范围的右边或者左边,例如数组{3, 4, 5},target为2或者数组{3, 4, 5},target为6,此时应该返回{-1, -1}
  • 情况二:target 在数组范围中,且数组中不存在target,例如数组{3,6,7},target为5,此时应该返回{-1, -1}
  • 情况三:target 在数组范围中,且数组中存在target,例如数组{3,6,7},target为6,此时应该返回{1, 1}

这三种情况都考虑到,说明就想的很清楚了。

接下来,在去寻找左边界,和右边界了。

采用二分法来去寻找左右边界,为了让代码清晰,我分别写两个二分来寻找左边界和右边界。

实现代码:

class Solution:
    def searchRange(self, nums: List[int], target: int) -> List[int]:
        if(len(nums) == 0):
            return [-1, -1]
        
        def findLeftBound(nums, target):#找到左边界
            left, right = 0, len(nums)-1
            while(left <= right):
                mid = int(left+(right-left)/2)
                if(nums[mid] == target):
                # 为了找到左边界,在遇到target值的时候还要继续往左边找
                    right = mid -1
                elif(nums[mid] > target):
                    right = mid - 1#右指针会指向最大小于target的值
                else:
                    left = mid + 1#左指针指向最小大于target的值
            if(left >= len(nums) or nums[left] != target):
                return -1
            else:
                return left

        def findRightBound(nums, target):#找到右边界
            left, right = 0, len(nums)-1
            while(left <= right):
                mid = int(left+(right-left)/2)
                if(nums[mid] == target):
                # 为了找到右边界,在遇到target值的时候还要继续往左边找
                    left = mid + 1
                elif(nums[mid] > target):
                    right = mid - 1#右指针会指向最大小于target的值
                else:
                    left = mid + 1#左指针指向最小大于target的值
            if(right < 0 or nums[right] != target):
                return -1
            else:
                return right

        leftBound = findLeftBound(nums, target)
        rightBoud = findRightBound(nums, target)
        return[leftBound, rightBoud]
        

类似题目3:69. x 的平方根 

给你一个非负整数 x ,计算并返回 x 的 算术平方根 。

由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。

注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5) 或者 x ** 0.5 。

示例 1:

输入:x = 4
输出:2

示例 2:

输入:x = 8
输出:2
解释:8 的算术平方根是 2.82842..., 由于返回类型是整数,小数部分将被舍去。

提示:

  • 0 <= x <= 231 - 1

算法思想: 

由于 x 平方根的整数部分 ans 是满足 k ^ 2 ≤ x 的最大 k 值,因此我们可以对 k 进行二分查找,从而得到答案。
二分查找的下界为 0,上界可以粗略地设定为 x。在二分查找的每一步中,我们只需要比较中间元素 mid 的平方与 x 的大小关系,并通过比较的结果调整上下界的范围。

实现代码:

class Solution:
    def mySqrt(self, x: int) -> int:
        left, right = 0, x
        while(left <= right):
            mid = (left + right) // 2 #//表示向下取整
            if(mid **2 == x):
                return mid
            elif(mid **2 < x):
                left = mid + 1#左指针指向最小大于target的值
            else:
                right = mid - 1#右指针会指向最大小于target的值
        return right

类似题目4:367. 有效的完全平方数

给定一个 正整数 num ,编写一个函数,如果 num 是一个完全平方数,则返回 true ,否则返回 false 。

进阶:不要 使用任何内置的库函数,如  sqrt 。

示例 1:

输入:num = 16
输出:true

示例 2:

输入:num = 14
输出:false

提示:

  • 1 <= num <= 2^31 - 1

 实现代码:(算法思路跟这个题目69. x 的平方根一样):

class Solution:
    def isPerfectSquare(self, num: int) -> bool:
        left, right = 1, num
        while(left <= right):
            mid = (left + right) // 2
            if(mid **2 == num):
                return True
            elif(mid **2 < num):
                left = mid + 1
            else:
                right = mid - 1
        return False

127. 移除元素-双指针法(快慢指针法)

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。

不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

算法思想:

 实现代码:

class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
    #双指针左移覆盖法
        left = 0#左指针left 指向下一个将要赋值的位置
        for right in range(len(nums)):#右指针 right指向当前将要处理的元素
            if(nums[right] != val):
                nums[left] = nums[right]
                left += 1
        return left

 类似题目1 26. 删除有序数组中的重复项 - 双指针之快慢指针

给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。

由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有 k 个元素,那么 nums 的前 k 个元素应该保存最终结果。

将最终结果插入 nums 的前 k 个位置后返回 k 。

不要使用额外的空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

解题思路:
题意:删除有序数组重复项,把去重后的数字放在输入数组的前面 n 个位置,返回 n.

看到题目标题的第一反应,当然是用 set !set 就是为了实现去重的。但是题目要求我们进行原地操作,并且时间复杂度是 O(1),因此就不能开辟另外的空间

双指针:
题目需要我们把去重后的结果保存到原本的数组中,所以想到必须有一个指针指向当前需要把结果放在哪个位置。还要一个指针指向当前应该放到哪个元素。

  • 慢指针作为基准,快指针用于寻找与慢指针不同的元素。
  • 如果快指针和慢指针指向的元素不等,则把快指针指向的元素放到慢指针的下一个位置。
  • 慢指针右移,把新的元素作为基准。

实现代码:

class Solution:
    def removeDuplicates(self, nums: List[int]) -> int:
        left = 0#慢指针
        for right in range(1, len(nums)):#right表示快指针
            if(nums[left] != nums[right]):
#如果快指针和慢指针指向的元素不等,则把快指针指向的元素放到慢指针的下一个位置。
                left += 1
                nums[left] = nums[right]
        return left+1

类似题目2 283. 移动零

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

请注意 ,必须在不复制数组的情况下原地对数组进行操作。

 

实现代码:(算法思想同 类似题目1 26. 删除有序数组中的重复项 ) 

class Solution:
    def moveZeroes(self, nums: List[int]) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        left = 0
        for right in range(len(nums)):
            if(nums[right] != 0):
                nums[left] = nums[right]
                left += 1
        for i in range(left, len(nums)):
            nums[i] = 0

类似题目3:977. 有序数组的平方

给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。

示例 1:

输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]

示例 2:

输入:nums = [-7,-3,2,3,11]
输出:[4,9,9,49,121]

提示:

  • 1 <= nums.length <= 104
  • -104 <= nums[i] <= 104
  • nums 已按 非递减顺序 排序

算法分析:

同样地,我们可以使用两个指针分别指向位置 000 和 n−1n-1n−1,每次比较两个指针对应的数,选择较大的那个逆序放入答案并移动指针。

实现代码:

class Solution:
    def sortedSquares(self, nums: List[int]) -> List[int]:
        # for i in range(len(nums)):
        #     nums[i] = nums[i]**2
        # nums = sorted(nums)
        # return nums
        res = [0 for _ in range(len(nums))]
        left, right, pos = 0, len(nums)-1, len(nums)-1
        #从最后开始放较大的那个数字
        #因为left或者right开始的时候一定是指向那个平方最大的那个数
        while(left <= right):
            if((nums[left] **2) > (nums[right] **2)):
                res[pos] = nums[left] **2
                left += 1
            else:
                res[pos] = nums[right] **2
                right -= 1
            pos -= 1
        return res

 

 

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

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

相关文章

什么是MQ

MQ概述 MQ全称 Message Queue&#xff08;消息队列&#xff09;&#xff0c;是在消息的传输过程中保存消息的容器。多用于分布式系统之间进 行通信。 分布式系统之间进行通信&#xff1a; 远程调用&#xff1a;各系统间直接通过远程调用的方式&#xff1b; 借助第三方完成系统…

【GlobalMapper精品教程】019:基于DSM提取离散随机点的高程信息

本文讲解在globalmapper中,基于DSM提取离散随机点的高程信息,配套数据为data019.rar。 文章目录 1. 离散点创建2. 提取离散点高程信息3. 高程标注1. 离散点创建 本文在ArcGIS中,根据给定的范围,随机生成离散点,如下图: 拓展阅读: ArcGIS根据范围创建随机点教程:【ArcG…

关于Kdo N3,1380099-68-2,3-脱氧-D-甘露-辛酸(Kdo)相关物理化学知识了解下

基础产品数据&#xff08;Basic Product Data&#xff09;&#xff1a; CAS号&#xff1a;1380099-68-2 中文名&#xff1a;2-酮基-3-脱氧辛酸叠氮糖 英文名&#xff1a;Kdo Azide&#xff0c;Kdo N3 结构式&#xff08;Structural&#xff09;&#xff1a; 试剂基团反应特点&a…

基于51单片机的波形发生器proteus仿真数码管LCD12864显示

仿真图1简介&#xff1a; 本系统采用51单片机作为系统的MCU&#xff08;具体型号见下图&#xff09;&#xff0c;该系统显示器为四位数码管&#xff0c;可实时显示波形的参数情况 可显示四种波形&#xff0c;分别是方波、正弦波、三角波、锯齿波。 该设计具有电压表功能&#…

C语言MFC导出dll回调函数方法详解

如何将回调函数导出来 这一章节主要讲述在导出函数的基础上如何将回调函数导出来。 C程序设计语言&#xff08;第1-3部分&#xff09;&#xff08;原书第4版&#xff09; 京东自营优惠价&#xff1a;&#xffe5;119.1立即抢购 回调函数的应用相信很多C程序猿儿们都不陌生吧…

弘玑Cyclone2022年产品发布会:人人可用的数字化工作平台——弘玑工作易

近日&#xff0c;在弘玑Cyclone“智无边界&#xff0c;数字未来”发布会上&#xff0c;弘玑Cyclone2022年超级自动化系列产品全新亮相&#xff0c;首席产品官贾岿博士带领产品团队以创新技术对新时代语境下的数字生产力进行了全新解读。 本文将为大家分享本次发布会重磅推出的…

为什么要让员工入职流程实现自动化

人和人之间的第一印象非常重要&#xff0c;一段缘分能不能开始&#xff0c;就看第一印象够不够给力了。其实&#xff0c;公司和新员工之间也存在着这样的关系&#xff0c;但也有些许差别。公司对新员工的第一印象&#xff0c;更多是从第一次见面的时候就产生了&#xff0c;而新…

NodeJs实战-待办列表(4)-解决待办事项中文乱码问题

NodeJs实战-待办列表4-解决待办事项中文乱码问题乱码问题在哪里产生的定位乱码问题VSCode 启动 NodeJs 调试模式浏览器中调试JS效果图执行添加执行完成乱码问题在哪里产生的 运行第3节的server.js, 当添加中文待办事项时候&#xff0c;会产生中文乱码问题。乱码可能在以下地方…

一款超好用的开源密码管理器?

程序员宝藏库&#xff1a;https://gitee.com/sharetech_lee/CS-Books-Store DevWeekly收集整理每周优质开发者内容&#xff0c;包括开源项目、资源工具、技术文章等方面。 每周五定期发布&#xff0c;同步更新到 知乎&#xff1a;Jackpop 。 欢迎大家投稿&#xff0c;提交iss…

最新消息:2022高被引科学家名单已公布,都想成为高被引,到底应该怎么做?(附名单)

11月15日&#xff0c;科睿唯安发布了2022年“高被引科学家”名单。该名单旨在遴选全球自然科学和社会科学领域最具影响力的研究人员。入选“高被引科学家”名单&#xff0c;意味着该学者在其所研究领域具有世界级影响力&#xff0c;其科研成果为该领域发展作出了较大贡献。 全球…

百度全景数据采集与分析

1、百度街景是什么 全景是通过将平面数字图像转换为三维空间&#xff0c;从而带来拟真交互体验的地图浏览方式。 全景技术通过专业相机将现实世界的空间场景捕捉下来&#xff0c;利用软件将多幅平面照片拼接合成&#xff0c;并模拟成三维空间的360度全景景观。全景具有真实感强…

127. 单词接龙

127. 单词接龙 字典 wordList 中从单词 beginWord 和 endWord 的 转换序列 是一个按下述规格形成的序列 beginWord -> s1 -> s2 -> … -> sk&#xff1a; 每一对相邻的单词只差一个字母。对于 1 < i < k 时&#xff0c;每个 si 都在 wordList 中。注意&…

linux线程互斥锁

互斥量mutex 大部分情况&#xff0c;线程使用的数据都是局部变量&#xff0c;变量的地址空间在线程栈空间内&#xff0c;这种情况&#xff0c;变量归属单个线程&#xff0c;其他线程无法获得这种变量。 但有时候&#xff0c;很多变量都需要在线程间共享&#xff0c;这样的变量…

基于粒子群优化算法的冷热电联供型综合能源系统运行优化附Matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

JAVA图书管理练习

目录0.前言1.书类(BOOK)1.1 Book1.2 BookList2. User类2.1 user类2.2 AdminUser类2.3 NormalUser类3.Operation类3.1 添加图书3.2 删除图书3.3 查找图书3.4 展示图书3.5 退出系统3.6 借阅图书3.7 归还图书0.前言 1.在学习了面向对象,接口继承等语法后,综合使用这些语法完成一个…

【第九章】vim 程序编辑器

文章目录vi与vimvi的使用范例按键说明一般指令模式可用的按钮说明&#xff1a;光标移动、复制贴上、搜寻取代等一般指令模式切换到编辑模式的可用的按钮说明一般指令模式切换到命令行界面的可用按钮说明vim的暂存盘、救援回复与打开时的警告讯息vi与vim 一、Linux上面的指令都…

Java#12(String中的常用方法)

目录 一.String中的方法substring 1.作用:截取字符串 2.格式:对象名.substring(开始的索引,结束的索引(没写就截到结尾)) 3.返回类型是String,所以要用一个字符串对象来接收 4.特点: 二.String中的办法replace 1.作用:替换字符串中的内容 2.格式:对象名.replace("要…

【面试题】flex布局画色子

1. flex布局 flex属性作用flex-direction设置主轴的方向justify-content设置主轴上的子元素排列方式align-items设置侧轴上的子元素排列方式flex-wrap设置子元素是否换行align-self设置子元素在侧轴的对齐方式 2. 通过flex布局画色子 <!DOCTYPE html> <html lang&qu…

Zotero文献管理软件入门使用方法:软件下载、文献导入、引文插入

本文介绍文献管理软件Zotero的基础使用方法&#xff0c;包括软件下载与安装、文献与PDF导入、在Word中插入参考文献等的方法。 在EndNote文献输出引用格式自定义修改与编辑界面解读&#xff08;https://blog.csdn.net/zhebushibiaoshifu/article/details/115221112&#xff09;…

Mysql、Hive、Sqoop的安装及配置

Mysql的安装及配置 1、查看系统安装的MariaDB rpm -qa|grep mariadb2、删除查询到的MariaDB&#xff0c;这里的mariadb-libs-5.5.68-1.el7.x86_64是通过上一步查出来的 rpm -e --nodeps mariadb-libs-5.5.68-1.el7.x86_643、执行以下命令下载并安装mysql5.7 wget http://de…