数组相关面试题

news2025/1/16 13:43:28

1、原地移除数组中所有的元素val,要求时间复杂度为O(N),空间复杂度为O(1)。

        OJ链接:27. 移除元素 - 力扣(LeetCode)

        分析:

法1:挪到数据,思路如顺序表的头删,将后面的数据向前挪动将其覆盖即删除成功。时间复杂度——做最坏的打算,如果数组所有元素都等于val,则时间复杂度为O(N^2),不符合要求。

法2:创建一块额外的空间dst,将原数组中不等于val的值拷贝到dst中,再将dst拷贝回原数组即可。图示:

但是该法的空间复杂度为O(N),不符合要求。

法3:法2空间复杂度不符合要求,那我们能不能就在原数组上挪动数据呢?当然是有的,这就双指针法(双下标)——创建两个指针(下标)src,dst指向原数组,src遍历原数组,如果nums[src] != val,则nums[dst++] = nums[src];如果nums[src] == val,则src++。图示:

        法3代码演示:

int removeElement(int* nums, int numsSize, int val)
{
    int src = 0;
    int dst = 0;
    while(src < numsSize)
    {
        if(nums[src] != val)
        {
            nums[dst++] = nums[src++];
        }
        else
        {
            src++;
        }
    }
    return dst;
}

2、删除排序数组中的重复项。

        OJ链接:26. 删除有序数组中的重复项 - 力扣(LeetCode)

        要求:时间复杂度0(N),空间复杂度O(1)        

分析:

        ①删除有序数组中的重复项,返回删除后的数组新长度,也叫去重算法。

        ②思路依旧使用双指针法:只是有了一些变化。创建两个伪指针(即定义两个下标变量),分别为src开始指向数组的第二个元素,dst开始指向数组的第一个元素;src遍历数组,每一次遍历时都要判断src位置是否等于dst位置,相等则将src位置的值拷贝到dst位置,同时dst位置向后+1。最后返回dst+1即可(一位dst开始时指向的数组的第一个元素,数组的下标从0开始,所以最后返回时要+1)。图示:

相当于src指针遍历数组,dst指针存储数组去重之后的新数据。

        代码演示:

int removeDuplicates(int* nums, int numsSize)
{
    //定义两个下标变量
    int src = 1;
    int dst = 0;
    //去重
    while(src < numsSize)
    {
        if(nums[src] == nums[dst])
        {
            src++;
        }
        else
        {
            nums[++dst] = nums[src++];
        }
    }
    //注意数组的下标从0开始,所以dst+1
    return dst + 1;
}

3、合并两个有序数组。

        OJ链接:88. 合并两个有序数组 - 力扣(LeetCode)

        分析:

法1:开辟额外的空间:①开辟新数组大小为m+n;②遍历比较两个数组(循环条件:有一个数组遍历结束即循环结束)。如果nums1[begin1] < nums2[begin2],则先将begin1位置的值拷贝到新数组;否则先将begin2位置的值拷贝到新数组,再begin2++。③将剩余的数组直接拷贝到新数组后面;④最后将新数组拷贝回nums1即可。图示:

时间复杂度O(M+N),空间复杂度O(M+N)。

法2:原地合并数组:①定义三个下标(伪指针):end1指向nums1有效数据的最后一个;end2指向nums有效数据的最后一个;dst指向合并数组nums1的最后一个;②逆向双指针:end1和end2两个指针从后向前遍历比较两个数组(为什么不从前往后遍历呢?因为从前遍历,每一次插入都要向后挪动数据),有一个数组遍历结束循环即停止。如果nums1[end1]>nums2[end2],则nums1[dst--]=nums1[end1--];否则nums1[dst--]=nums2[end2--]。③特殊情况:如果是nums2没有遍历结束,则需继续将nums2剩余的元素依次拷贝到nums1前面。图示:

时间复杂度:O(M+N);空间复杂度O(1).

        法1:开辟额外的空间代码演示:

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n)
{
    //开辟新数组大小m+n
    int dst[m + n];
    //分别定义三个数组下标变量
    int begin1 = 0;
    int begin2 = 0;
    int begin3 = 0;
    //先遍历比较两数组(循环条件:有一个数组遍历结束即循环结束)
    //如果nums1[begin1]<nums2[begin2],则先将begin1位置的值拷贝到新数组,再begin1++
    //否则先将begin2位置的值拷贝到新数组,再begin2++
    while(begin1 < m && begin2 < n)
    {
        if(nums1[begin1] < nums2[begin2])
        {
            dst[begin3++] = nums1[begin1++];
        }
        else
        {
            dst[begin3++] = nums2[begin2++];
        }
    }
    //将剩余的数组直接拷贝到新数组后面
    if(begin1 < m)
    {
        memmove(dst + begin3,nums1 + begin1,(m - begin1)*sizeof(int));
    }
    else if(begin2 < n)
    {
        memmove(dst + begin3,nums2 + begin2,(n - begin2)*sizeof(int));
    }
    //最后将新数组拷贝回nums1即可
    memmove(nums1,dst,(m + n)*sizeof(int));
}

        法2:原地合并数组代码演示:

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n)
{
    //定义三个下标
    int end1 = m - 1;//指向nums1有效数据的最后一个
    int end2 = n - 1;//指向nums2数据的最后一个
    int dst = m + n -1;//指向合并数组nums1的最后一个
    //逆向双指针合并:end1和end2两个指针从后往前遍历两个数组,有一个数组遍历结束即停止。
    while(end1 >= 0 && end2 >=0)
    {
        if(nums1[end1] > nums2[end2])
        {
            nums1[dst--] = nums1[end1--];
        }
        else
        {
            nums1[dst--] = nums2[end2--];
        }
    }
    //特殊情况:如果nums2没有遍历完,则需将nums2前面的元素拷贝到nums1中
    while(end2 >= 0)
    {
        nums1[dst--] = nums2[end2--];
    }
}

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

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

相关文章

What does rail-to-rail mean (Rail-to-Rail Op amp) ?

What does rail-to-rail mean (Rail-to-Rail Op amp) ?

网络安全进阶学习第十九课——CTF之密码学

文章目录 一、密码学简介二、密码设计的根本目标三、古典密码1、摩斯密码CTF-题目展示 2、换位密码1&#xff09;栅栏密码2&#xff09;凯撒密码3&#xff09;曲路密码4&#xff09;列移位密码 3、替换密码1&#xff09;移位密码2&#xff09;简单替换密码3&#xff09;埃特巴什…

10 Ubuntu下配置STMCubeMX与CLion IDE联合环境搭建(不包含下载CLion的教程)

序言 果然作为一名测控系的学生&#xff0c;纯搞视觉多少还是有点与专业脱节&#xff0c;决定入坑嵌入式。选择STM32进行入门&#xff0c;并且使用CubeMX加CLion作为我的第一个真正意义上的嵌入式开发环境&#xff08;大一的时候玩过一段时间&#xff0c;但是没什么技术&#…

java创建excel文件和解析excel文件

创建excel文件 package com.bjpowernode.crm.poi;import org.apache.poi.hssf.usermodel.*; import org.apache.poi.ss.usermodel.HorizontalAlignment;import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.…

用于3D模具和模型制作:数控机床进行加工软件DeskProto【常用CAM(计算机辅助制造)软件】

DeskProto是一款用于计算机数控&#xff08;CNC&#xff09;机床的三维模型加工的软件&#xff0c;它的技术原理和操作方法涵盖了以下方面&#xff1a; 技术原理&#xff1a; DeskProto的技术原理基于计算机辅助设计&#xff08;CAD&#xff09;和计算机数控&#xff08;CNC&…

Day43:VUEX

1. 基本介绍 这里介绍的VueX是匹配Vue3的V4版本&#xff0c;它绝大多数功能使用都和之前基本保持一致。 1.1 官方定义 先一起看一下官网对于VueX的定义&#xff1a; Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 库。它采用集中式存储管理应用的所有组件的状态&…

Mybatis入门与数据库连接池以及lombok插件

我们做为后端程序开发人员&#xff0c;通常会使用Java程序来完成对数据库的操作。Java程序操作数据库&#xff0c;现在主流的方式是&#xff1a;Mybatis。 什么是MyBatis? MyBatis是一款优秀的 持久层 框架&#xff0c;用于简化JDBC的开发。 MyBatis本是 Apache的一个开源项…

typescrip接口 interface详解,以及ts实现多态

ts 接口 当一个对象类型被多次使用时,一般会使用接口(interface)来描述对象的类型,达到复用的目的 示例如下 当一个对象类型被多次使用时,可以看到,很明显代码有大量的冗余 let personTom: { name: string, age?: number, sayHi(name: string): void } {name: Tom,sayHi(n…

从头开始制作扩散模型(实现快速扩散模型的简单方法)

一、说明 本文是关于自己从头开始构建扩散模型的教程。我总是喜欢让事情变得简单易行&#xff0c;所以在这里&#xff0c;我们避免了复杂的数学。这不是一个正常的扩散模型。相反&#xff0c;我称之为快速扩散模型。将仅使用卷积神经网络&#xff08;CNN&#xff09;来制作扩散…

LwIP介绍

文章目录 一、LwIP简介二、LwIP主要特性:三、文件说明lwip-2.1.3contrib-2.1.0一、LwIP简介 lwIP(Light weight IP)是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。LwIP是Light Weight (轻型)IP协议,有无操作系统的支持都可以运行。LwIP 的设…

【Obsidian】中编辑模式和阅读模式光标乱跳问题以及编辑模式中段落聚集的问题解决

前言 最近用Obsidian 软件写md笔记&#xff0c;但是当我分别使用编辑模式和阅读模式时出现了光标乱跳的问题。比如我在编辑模式&#xff0c;光标停留在第500行&#xff0c;但是切换成编辑模式就变成了1000行。而且光标根本没停在原来的位置。这样重新定位非常麻烦。 两种阅读…

mybati缓存了解

title: “mybati缓存了解” createTime: 2021-12-08T12:19:5708:00 updateTime: 2021-12-08T12:19:5708:00 draft: false author: “ggball” tags: [“mybatis”] categories: [“java”] description: “mybati缓存了解” mybatis的缓存 首先来看下mybatis对缓存的规范&…

Web服务(Web Service)

简介 Web服务&#xff08;Web Service&#xff09;是一种Web应用开发技术&#xff0c;用XML描述、发布、发现Web服务。它可以跨平台、进行分布式部署。 Web服务包含了一套标准&#xff0c;例如SOAP、WSDL、UDDI&#xff0c;定义了应用程序如何在Web上实现互操作。 Web服务的服…

第十九章、【Linux】开机流程、模块管理与Loader

19.1.1 开机流程一览 以个人计算机架设的 Linux 主机为例&#xff0c;当你按下电源按键后计算机硬件会主动的读取 BIOS 或 UEFI BIOS 来载入硬件信息及进行硬件系统的自我测试&#xff0c; 之后系统会主动的去读取第一个可开机的设备 &#xff08;由 BIOS 设置的&#xff09; …

线程安全问题的原因及解决方案

要想知道线程安全问题的原因及解决方案&#xff0c;首先得知道什么是线程安全&#xff0c;想给出一个线程安全的确切定义是复杂的&#xff0c;但我们可以这样认为&#xff1a;如果多线程环境下代码运行的结果是符合我们预期的&#xff0c;即在单线程环境应该的结果&#xff0c;…

基于 IntelliJ 的 IDE 将提供 Wayland 支持

导读对于使用 IntelliJ 开发环境的用户&#xff0c;JetBrains 一直致力于提供原生 Wayland 支持。 JetBrains 正在致力于为基于 IntelliJ 的 IDE 提供 Wayland 支持&#xff0c;以增强 Linux 桌面体验以及在 Windows Subsystem for Linux 下运行。 Wayland 支持功能尚未完成&…

Jmeter性能实战之分布式压测

分布式执行原理 1、JMeter分布式测试时&#xff0c;选择其中一台作为调度机(master)&#xff0c;其它机器作为执行机(slave)。 2、执行时&#xff0c;master会把脚本发送到每台slave上&#xff0c;slave 拿到脚本后就开始执行&#xff0c;slave执行时不需要启动GUI&#xff0…

专栏十:10X单细胞的聚类树绘图

经常在文章中看到对细胞群进行聚类,以证明两个cluster之间的相关性,这里总结两种绘制这种图的方式和代码,当然我觉得这些五颜六色的颜色可能是后期加的,本帖子只总结画树状图的方法 例一 文章Single-cell analyses implicate ascites in remodeling the ecosystems of pr…

zemax慧差与消慧差

基础设置&#xff1a; 该表面用于对系统的波前进行调制&#xff0c;得到想要的波前形状 通过理想透镜的光线在像空间聚焦&#xff0c;得到完美的球面波&#xff0c;经过调制可以模拟出任意的像差 这里的系数为泽尼克系数 1&#xff1a;平移 2&#xff1a;x轴倾斜 3&#x…

C盘简易无门槛清理指南

C盘在日常使用过程中会逐渐越来越少明明什么也没装&#xff0c;C盘空间却满了&#xff0c;导致最后爆满出现系统运行变慢&#xff0c;软件卡等现象。但随便删除一些东西&#xff0c;系统就崩溃了。本篇分析原因和介绍一些解决方法。 爆满原因主要分为四大类&#xff1a; 一&a…