Leetcode26-28,这几道简单有趣的算法题你都会吗?

2023-11-13

26-删除排序数组中的重复项

题目要求:

给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。

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

示例1:

给定数组	nums = [1,1,2]
函数应该返回新的长度 2 ,并且原数组nums的前两个元素被修改为1,2
你不需要考虑数组中超出新长度后面的元素。

示例2:

给定数组	nums = [0,0,1,1,1,2,2,3,3,4]
函数应该返回新的长度 5,并且原数组nums的前五个元素被修改为 0,1,2,3,4
你不需要考虑数组中超出新长度后面的元素

来简单分析一下这道题,首先数组是排过序的,也就是说我们不需要用别的什么花里胡哨的算法,只需要对数组遍历一下就行。

然后需要在原地删除重复出现的元素,同时不能使用额外的数组空间,这个是什么意思呢?其实也就是说,你不能新建一个数组,然后在遍历的时候发现不同的数就给放入新数组。这样的话就不是对原数组进行修改了,而且还用了额外的新空间。

我们知道数组是引用数据类型,也就是说我们对传入的数组做任何改变都会直接移植到原数组,那么我们需要做的就是直接对原数组操作就行了。

同时还有最后一个特别重要的条件:你不需要考虑数组中超出新长度后面的元素。哎,这句话什么意思?其实这句话就向我们提供了一种思路:双指针。为什么会这么想?注意题目中要求是在原地删除元素,我们刚开始想的重点可能都是怎么把元素删除,当我们不需要考虑超出新长度后面的元素的时候,我们就可以直接对原数组修改就行了,不需要把数组中的元素删除。

实现思路

双指针,一个指针用来遍历原数组,找到不同的元素,另一个指针用来修改数组。遍历数组的指针是较快的指针,修改数组的指针是较慢的指针,当快的指针找到一个不重复的元素的时候,慢指针向前一位,然后修改该位的元素为快指针发现的不重复元素。

代码(Java):

public int removeDuplicates(int[] nums) {
    int i = 0;	//i 慢指针  j 快指针
    for (int j = 1; j< nums.length; j++) {
        if (nums[i] != nums[j]) {
            i++;
            nums[i] = nums[j];
        }
    }
    return i+1;
}

代码(Python):

def removeDuplicates(nums):
        nums[:] = sorted(set(nums))
        return len(nums)

嘿嘿,Python没有用和Java相同的思路写了,如果想实现相同思路,大家自己可以试着写一下。咱们来分析一下如上的代码。

因为Python有个数据类型叫集合,只要set()一下,列表中的元素就不相同了,同时因为集合具有无序的特性,就用sorted()给去重后的集合排个序。那有同志可能要说了,为什么不直接一行代码:

return len(sorted(set(nums)))搞定,还得切个整个集合的片?

因为leetcode有要求嘛,需要在原地删除元素,也就是说,对引用的数组做操作,而在leetcode的代码框里面是这样的:

class Solution(object):
    def removeDuplicates(self, nums):
        nums[:] = sorted(set(nums))
        return len(nums)

也就是说,这是类的一个方法,如果在类中你写一个nums变量,那它只是一个新变量,并不是方法传入的那个nums,因此最后返回的长度只是那个新变量的长度,而不是原数组的长度。

27-移除元素

题目要求:

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

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

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

示例1:

给定 nums = [3,2,2,3], val = 3,

函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。

你不需要考虑数组中超出新长度后面的元素。

示例2:

给定 nums = [0,1,2,2,3,0,4,2], val = 2,

函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。

注意这五个元素可为任意顺序。

你不需要考虑数组中超出新长度后面的元素。

其实这道题跟上道题是十分类似的,上道题目是删除相同的元素,这道题是删除等于给定值的元素,实际上这道题比上一道更加简单了,如果上道题理解的同学可能已经对这道题有思路了。

实现思路

依然是双指针,遍历数组。题目要求移除等于指定值的元素,那我们就在遍历的时候如果碰到不等于指定值的元素,就用慢指针更改它位置上元素不久OK了。

代码(Java):

class Solution {
    public int removeElement(int[] nums, int val) {
        int i = 0;
        for (int j=0;j<nums.length;j++) {
            if (nums[j] != val) {
                nums[i] = nums[j];
                i++;
            }
        }
        return i;
    }
}

代码(Python):

class Solution(object):
    def removeElement(self, nums, val):
        i = 0
        for j in range(len(nums)):
            if nums[j] != val:
                nums[i] = nums[j]
                i += 1
        return i;

这次Python和Java实现方式相同了,大家可以对比看一下。

28-实现strStr()

题目要求:

给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。

示例1:

输入: haystack = "hello", needle = "ll"
输出: 2

示例2:

输入: haystack = "aaaaa", needle = "bba"
输出: -1

题目很简短,给定两个字符串,如果第二个字符串在第一个字符串中出现,那么返回它第一次出现的位置,如果没有出现,返回-1就行。

简单分析一下,什么时候会不出现?

首先,一种情况是haystackneedle长,这样子肯定不会存在。第二种情况就更好想了,就是单纯第二个字符串没有在第一个字符串中出现。

那如果出现了会有什么特征?也就是说第二个字符串在第一个字符串中能找到相同的部分,题目要求返回出现的第一个位置,那我们从前向后遍历第一个字符串就行了,如果某个元素和第二个字符串的首元素相同,那我们就挨着顺序对比下去,如果不相同,接着上次遍历到的位置继续遍历就行了,如果遍历到最后没有发现相同的部分,就返回-1。实际上,我们不需要遍历到第一个字符串的最后一个位置,为什么?因为剩下的长度小于第二个字符串的时候肯定不会再出现了。

实现思路

首先确定两个字符串的长度,用一根指针遍历haystack字符串,然后直接判断haystack字符串从当前位置到needle长度的部分是否和needle是相同的,如果相同,直接返回当前位置,如果不相同,继续向后遍历。

代码(Java):

class Solution {
  public int strStr(String haystack, String needle) {
        int haylen = haystack.length();
        int neelen = needle.length();
        for (int i = 0; i < haylen - neelen + 1; i++) {
            if (haystack.substring(i, i + neelen).equals(needle)) {
                return i;
                }
        }
    return -1;
    }
}

代码(Python):

class Solution:
    def strStr(self, haystack: str, needle: str) -> int:
        haylen = len(haystack)
        neelen = len(needle)
        for i in range(haylen-neelen +1):
            if haystack[i:i+neelen] == needle:
                return i
        return -1

好了,今天的题目分享就到这里,这都是题库里面非常简单的题目,注意消化分享,有不懂的地方多多留言交流哦~

你好,我是goldsunC

让我们一起进步吧!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Leetcode26-28,这几道简单有趣的算法题你都会吗? 的相关文章

随机推荐

  • Qt:十六进制字符串和十六进制互转

    Qt 十六进制字符串和十六进制互转 前言 一 字符串转换十六进制 1 封装函数 2 函数调用示例 二 16进制转换字符串 前言 网上查了不少方式 踩了不少坑 最终这个方式是我目前使用感觉较好的一种 具体出处已经没印象了 这里放出完整代码供大
  • Spring(二)IOC容器的初始化流程

    文章目录 一 Spring 核心容器类 1 1 BeanFactory 1 2 ApplicationContext 1 3 BeanDefinition 二 IOC容器的初始化 2 1 基于Xml的IOC容器的初始化 2 1 1 寻找入口
  • 15个顶级Java多线程面试题及答案

    1 现在有T1 T2 T3三个线程 你怎样保证T2在T1执行完后执行 T3在T2执行完后执行 这个线程问题通常会在第一轮或电话面试阶段被问到 目的是检测你对 join 方法是否熟悉 这个多线程问题比较简单 可以用join方法实现 2 在Ja
  • LLM在放射科学中应用潜力

    本论文在全球范围内评估了 31 个大型语言模型 LLM 在解读放射科报告并从放射学发现中推导出诊断信息 impression 任务上的表现 这是目前已知的对全球 LLM 用于放射科学自然语言处理 NLP 进行的最全面评估之一 该研究通过在这
  • 8款常见的自动化测试开源框架

    在如今开源的时代 我们就不要再闭门造车了 热烈的拥抱开源吧 本文针对性能测试 Web UI 测试 API 测试 数据库测试 接口测试 单元测试等方面 为大家整理了github或码云上优秀的自动化测试开源项目 希望能给大家带来一点帮助 一 性
  • 运维体系的构建

    文章目录 一 前言 二 基础 2 1 项目摸底 2 2 做一个好辅助 2 3 学习业务 2 4 标准与流程 2 5 维护 三 进阶 3 1 系统 服务优化 3 2 工作流程优化 3 3 规矩 3 4 运维管理平台 一 前言 运维的基础工作通
  • php lazy loading,React丨用户体验丨hook版 lazy loading

    我们都知道随着单页应用 bundle 的体积不断增大 会造成首次加载时间过长 白屏时间过长 过程中会加载了我们首页没有必要看到的一些 页面 组件 js文件 所以我们需要对 bundle 文件进行拆分来进行按需加载 懒加载 这里需要用到 we
  • Xilinx FIFO Generator 需要注意RST复位

    Xilinx FIFO Generator 需要注意RST复位 系列文章推荐 Xilinx FIFO Generator 需要注意RST复位 Xilinx FIFO Generator 需要注意Actual Depth Xilinx FIF
  • cvCloneImage()内存泄漏解决方法, cvCloneImage()和cvCopy()的区别

    转自 http blog csdn net stellar0 article details 8741759 cvCloneImage 每次使用时编译器会分配新的内存空间 不会覆盖以前的内容 所以如果在循环中使用内存会迅速减小 每次用完都需
  • Python 计算机视觉(六)—— OpenCV 进行图像量化与采样

    对于信号的采样可以参考我之前的文章 数字信号处理 2 1 采样 对于信号的量化可以参考 数字信号处理 2 4 ADC 中的有限字长效应 在本篇文章中绘图使用到了 matplotlib 库 需要了解学习可以参考我之前写的用来总结这个绘图库的文
  • 一文看懂Spark中reduceByKey 和 groupByKey 的区别

    目录 一 先看结论 二 举例 画图说明 1 实现的功能分别是什么 1 groupByKey 实现 WordCount 2 reduceByKey 实现 WordCount 2 画图解析两种实现方式的区别 1 groupByKey 实现 Wo
  • C++深拷贝与浅拷贝以及写时复制

    深拷贝和浅拷贝的优缺点 看了深拷贝 浅拷贝优缺点 我们知道浅拷贝效率高 但涉及到指针引用等会涉及到指针的多次释放导致悬挂指针 深拷贝 不会造成指针悬挂的问题 但会浪费空间以及效率较低的问题 下面看下用到浅拷贝的情况 include
  • TCP通信发送和接收数据(Socket、ServerSocket)、TCP通信案例

    目录 TCP TCP发送接收数据 发送数据 Socket 接收数据 ServerSocket TCP通信案例1 TCP接收数据后给出反馈案例2 TCP接收数据后给出反馈案例3 TCP接收数据后给出反馈案例4 TCP 概述 TCP通信协议是一
  • C++实现——三子棋游戏

    题目描述 两个人玩三子棋游戏 即在3 3的矩阵上下棋 一个人画叉一个人画圈 谁先出现成行或成列或成对角线三个相同的棋子就算谁赢 编写算法实现 判断给定棋局的状态 用1代表先手 2代表后手 出现的六种状态为 1won 2won x 代表棋局错
  • 爬虫逆向——某建筑市场监管平台的滑块验证码分析

    目录 网址链接 正文 一 思路分析 二 图片处理 三 完整代码 网址链接 aHR0cHM6Ly9nY3htLmh1bmFuanMuZ292LmNuL2RhdGFzZXJ2aWNlLmh0bWw bs64解密可见 正文 注 分步的代码为示例代
  • GD32F103与STM32F103的区别 2021.6.2

    GD32F103和STM32F103区别介绍 关键词Key words GD32F103 STM32F103 摘要Abstract 本文主要是GD32F103和STM32F103区别进行介绍 目录 简介 GD32和STM32的区别 2 1
  • 正交向量 正交矩阵

    如何判断向量正交 内积 对应位置相乘再求和 是内积 卷积 加上滑动窗口 判断向量是否正交 两个向量正交 求其内积 看是否为0 若为零 则正交 在空间上向量垂直就正交 例子 a 1 1 0 b 1 1 0 则内积 a b 1 1 1 1 0
  • Linux教程:如何使用kubeadm从头到尾搭建k8s单节点服务并部署dashboard

    前言 在以往教程中 我们使用的是Minikube快速搭建的k8s服务 但这种方式只能在开发环境中使用 并不推荐生产环境 官方的推荐的方案是采用kubeadm快速搭建 kubeadm是官方社区推出的一个用于快速部署kubernetes集群的工
  • 改造vue-element-admin 的登录功能,变成从后台数据库中验证登录

    改造vue element admin 的登录功能 变成从后台数据库中验证登录 首先了解登录时前段需要什么样的数据 要知道vue element admin 这个后台开发模板是集成非常多我们日常开发网站的基本功能 所以我们在改造登录功能的时
  • Leetcode26-28,这几道简单有趣的算法题你都会吗?

    26 删除排序数组中的重复项 题目要求 给定一个排序数组 你需要在原地删除重复出现的元素 使得每个元素只出现一次 返回移除后数组的新长度 不要使用额外的数组空间 你必须在原地修改输入数组并在使用O 1 额外空间的条件下完成 示例1 给定数组