版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
校招C++面试题库及答案解析单项选择题(共10题)1.以下关于const修饰指针的说法中,正确的是()A.constint*p表示p指向的内存地址不可修改B.int*constp表示p指向的内存值不可修改C.constint*constp表示p本身和指向的值都不可修改D.const修饰的指针无法进行任何类型转换【答案】C【解析】const修饰指针分为顶层const和底层const:顶层const表示指针本身存储的地址不可修改,底层const表示指针指向的内存值不可修改。选项A:constint*p为底层const,指向的值不可修改,但指针本身的地址可重新赋值,A错误。选项B:int*constp为顶层const,指针本身的地址不可修改,但指向的内存值可修改,B错误。选项C:constint*constp同时包含顶层和底层const,指针本身和指向的值均不可修改,C正确。选项D:const修饰的指针可进行类型转换,例如通过const_cast去除底层const属性(仅当原对象为非const时,修改值才合法,否则属于未定义行为),D错误。2.已知编译器默认对齐数为8,32位系统下,以下结构体的sizeof结果为()structTest{chara;intb;shortc;doubled;};A.24B.20C.16D.32【答案】A【解析】结构体大小遵循内存对齐规则,目的是提升硬件内存访问效率、保证平台兼容性,规则如下:1.每个成员的偏移量为「成员自身大小」与「编译器默认对齐数」的较小值的整数倍;2.结构体总大小为「所有成员中最大对齐数」与「默认对齐数」的较小值的整数倍。本题中各成员的大小和偏移计算:chara:大小1字节,对齐数为min(1,8)=1,偏移量为0(满足1的倍数),占用字节范围0~0。intb:大小4字节,对齐数为min(4,8)=4,偏移量需为4的倍数,下一个合法偏移为4,占用字节范围4~7。shortc:大小2字节,对齐数为min(2,8)=2,当前偏移8满足2的倍数,占用字节范围8~9。doubled:大小8字节,对齐数为min(8,8)=8,偏移量需为8的倍数,当前偏移10不满足,下一个合法偏移为16,占用字节范围16~23。结构体最大成员对齐数为8,总大小需为8的倍数,23+1=24满足要求,因此sizeof(Test)=24。3.以下关于C++中static关键字的说法,错误的是()A.全局静态变量的作用域仅限于定义它的源文件B.局部静态变量在程序运行期间只初始化一次C.类的静态成员函数可以直接访问类的非静态成员变量D.类的静态成员不属于某个具体的对象,由所有对象共享【答案】C【解析】static关键字在C++中有三类核心用法,分别作用于全局/局部变量、类成员:修饰全局变量:将全局变量的作用域限制为当前源文件,其他源文件无法通过extern访问,避免全局命名冲突。修饰局部变量:将变量的存储区域从栈转移到全局/静态存储区,生命周期延长为整个程序运行期,且仅在第一次执行到定义语句时初始化一次,后续函数调用不再初始化。修饰类成员(成员变量/成员函数):静态成员属于类级别,由所有类对象共享,不属于单个对象;静态成员函数没有this指针,因此无法直接访问非静态成员变量(非静态成员依赖具体对象的this指针访问),只能访问静态成员变量和静态成员函数。选项C中静态成员函数无法直接访问非静态成员变量,表述错误。4.以下关于C++虚函数的描述,正确的是()A.构造函数可以声明为虚函数B.析构函数可以声明为纯虚函数,且必须提供实现C.虚函数调用一定是动态绑定D.虚函数表属于类的每个对象,每个对象都有独立的虚表【答案】B【解析】虚函数是实现动态多态的核心,相关特性如下:选项A:构造函数不能声明为虚函数。构造函数执行时对象尚未完全构造,虚表指针(vptr)未完成初始化,无法进行动态绑定,因此构造函数声明为虚函数无意义,语法也不支持,A错误。选项B:析构函数可以声明为纯虚函数,此时类为抽象类,无法实例化。但纯虚析构函数必须提供实现,因为派生类析构时会自动调用基类析构函数,若没有实现会触发链接错误,B正确。选项C:虚函数调用不一定是动态绑定。只有通过基类指针或基类引用调用虚函数时才会触发动态绑定;通过对象直接调用虚函数属于静态绑定,编译期即可确定调用的函数版本,C错误。选项D:虚函数表(vtable)是类级别的资源,每个包含虚函数的类只有一份虚表,存储所有虚函数的地址;每个对象仅存储一个虚表指针(vptr),指向所属类的虚表,而非独立的虚表,D错误。5.以下关于std::vector的扩容机制,说法正确的是()A.vector每次扩容会将容量增加当前大小的1.5倍,所有编译器实现一致B.vector扩容时会调用元素的拷贝构造函数或移动构造函数(C++11及以后)C.vector的size()和capacity()返回值始终相等D.vector扩容时不会导致迭代器失效【答案】B【解析】std::vector底层为连续动态数组,其扩容机制特性如下:选项A:不同编译器的vector扩容倍数实现不一致,GCC默认扩容为当前容量的2倍,VS默认扩容为1.5倍,均为时间与空间的权衡,并非统一标准,A错误。选项B:C++11引入移动语义后,vector扩容时会优先调用元素的noexcept移动构造函数(避免移动过程中抛异常导致旧数据损坏),若元素没有noexcept移动构造,则回退到拷贝构造,B正确。选项C:size()返回当前已存储的元素数量,capacity()返回当前分配的内存可容纳的最大元素数量,扩容后capacity大于size,二者不始终相等,C错误。选项D:扩容时会重新申请新的连续内存空间,并将旧元素迁移到新内存,随后释放旧内存,因此所有指向旧内存的迭代器、指针、引用都会全部失效,D错误。6.下列关于C++指针和引用的说法,错误的是()A.引用必须在定义时初始化,指针可以在定义后再赋值B.对引用执行sizeof运算得到的是所指向对象的大小,对指针执行sizeof运算得到的是指针自身的大小C.引用不能重新绑定到其他对象,指针可以修改其指向的内存地址D.引用作为函数返回值时,返回局部变量的引用是合法的,不会产生悬空问题【答案】D【解析】引用是C++引入的对象别名机制,与指针的核心区别如下:选项A:引用本质是对象的别名,必须在定义时绑定到具体对象,无法后续重新绑定;指针是存储内存地址的变量,可以先定义再赋值,甚至为空,A正确。选项B:语法层面引用是对象的别名,因此对引用执行sizeof运算等价于对目标对象执行sizeof;指针是独立的变量,其大小由平台决定(32位系统4字节,64位系统8字节),与指向对象的大小无关,B正确。选项C:引用一旦初始化就无法重新绑定到其他对象,修改引用的值只会修改目标对象的值;指针可以随时修改存储的地址,指向其他对象,C正确。选项D:函数返回局部变量的引用属于非法行为,局部变量存储在栈上,函数执行结束后栈帧销毁,局部变量被回收,返回的引用会成为悬空引用,访问该引用属于未定义行为,D错误。7.以下关于C++11中auto关键字的说法,正确的是()A.auto可以用来声明类的非静态成员变量的类型B.auto推导变量类型时,会忽略表达式的顶层const和引用属性C.auto可以直接用于普通函数形参的类型声明D.auto推导的变量可以不初始化【答案】B【解析】auto是C++11引入的类型推导关键字,用于简化代码、提升开发效率,其推导规则如下:选项A:C++11不允许用auto推导类的非静态成员变量类型,该特性到C++17才支持,A错误。选项B:auto推导时会忽略表达式的顶层const和引用属性,仅保留底层const。例如constinta=10;autob=a;推导得到b的类型为int(顶层const被忽略);int&c=a;autod=c;推导得到d的类型为int(引用属性被忽略),B正确。选项C:C++11不允许用auto声明普通函数的形参类型,仅可用于泛型lambda的参数;普通函数形参用auto的特性到C++20才正式支持,C错误。选项D:auto的类型推导依赖初始化表达式,因此auto变量必须在定义时初始化,否则无法推导类型,D错误。8.有如下代码,程序运行后的输出结果是()usingnamespacestd;classBase{public:Base(){cout<<"Base构造";}~Base(){cout<<"Base析构";}};classDerived:publicBase{public:Derived(){cout<<"Derived构造";}~Derived(){cout<<"Derived析构";}};intmain(){Derivedd;return0;}A.Base构造Derived构造Derived析构Base析构B.Derived构造Base构造Base析构Derived析构C.Base构造Derived构造Base析构Derived析构D.Derived构造Base构造Derived析构Base析构【答案】A【解析】继承体系下的构造与析构顺序遵循固定规则:构造顺序:先执行基类构造函数,再执行派生类构造函数(派生类构造依赖基类成员的初始化)。析构顺序:先执行派生类析构函数,再执行基类析构函数(与构造顺序相反,避免基类先销毁导致派生类访问非法内存)。本题中定义Derived类对象d,先调用Base构造函数输出“Base构造”,再调用Derived构造函数输出“Derived构造”;程序结束对象销毁时,先调用Derived析构函数输出“Derived析构”,再调用Base析构函数输出“Base析构”,最终输出为“Base构造Derived构造Derived析构Base析构”。延伸考点:若基类析构函数未声明为虚函数,通过基类指针指向派生类对象并delete时,只会调用基类析构函数,导致派生类资源泄漏,因此基类析构函数通常声明为虚函数。9.以下关于std::map和std::unordered_map的说法,错误的是()A.map的底层实现是红黑树,unordered_map的底层是哈希表B.map的元素是有序的,unordered_map的元素是无序的C.map的查找插入删除时间复杂度都是O(logn),unordered_map平均是O(1),最坏是O(n)D.unordered_map的键类型只需要支持<运算符比较,map的键需要支持哈希函数和相等比较【答案】D【解析】map和unordered_map是C++STL中两种常用的关联式容器,核心区别在于底层实现与性能特性:选项A:map底层为平衡二叉搜索树(红黑树),unordered_map底层为哈希表(链地址法解决哈希冲突),A正确。选项B:红黑树是有序结构,因此map的元素按键的升序排列(默认小于号比较);哈希表为无序结构,unordered_map的元素存储顺序与键的大小无关,B正确。选项C:红黑树的插入、删除、查找均需遍历树,时间复杂度稳定为O(logn);哈希表的插入、删除、查找平均时间复杂度为O(1),最坏情况(所有元素哈希冲突到同一个桶)时间复杂度退化为O(n),C正确。选项D:map依赖红黑树的排序特性,因此键类型需要支持<运算符比较(或自定义比较函数);unordered_map依赖哈希表计算哈希值和冲突判断,因此键类型需要支持哈希函数和==运算符比较,选项表述完全相反,D错误。10.以下关于C++智能指针的说法,正确的是()A.shared_ptr可以直接指向栈上的对象,不会产生问题B.unique_ptr可以被拷贝和赋值C.weak_ptr可以直接访问所指向的对象,不需要通过lock()方法D.shared_ptr的循环引用会导致内存泄漏,weak_ptr可以解决循环引用问题【答案】D【解析】C++11引入的智能指针用于管理动态内存,避免内存泄漏,核心包括shared_ptr、unique_ptr、weak_ptr:选项A:shared_ptr默认使用delete释放指向的内存,若指向栈上的对象,delete栈地址属于未定义行为,会导致程序崩溃,A错误。选项B:unique_ptr是独占式智能指针,同一时间只能有一个unique_ptr指向某个对象,因此不支持拷贝构造和拷贝赋值,仅支持移动语义(转移所有权),B错误。选项C:weak_ptr是弱引用指针,不拥有对象的所有权,不会增加引用计数,无法直接访问对象,必须调用lock()方法获取对应的shared_ptr(若对象已被销毁,lock()返回空shared_ptr)后才能访问,C错误。选项D:shared_ptr采用引用计数管理对象生命周期,当两个对象互相持有对方的shared_ptr时,会导致循环引用,二者的引用计数始终为1,无法被自动释放,造成内存泄漏;使用weak_ptr替代其中一方的shared_ptr,由于weak_ptr不增加引用计数,不会导致循环引用问题,D正确。简答题(共5题)1.请简述C++中堆和栈的区别,至少从5个维度说明。【答案解析】堆和栈是C++中两种核心的内存区域,区别主要体现在以下维度:(1)管理方式不同:栈由编译器自动管理,无需手动操作,函数调用结束后栈帧自动销毁,局部变量自动释放;堆由程序员手动管理,需要通过new/malloc分配,delete/free释放,若未主动释放会造成内存泄漏。(2)空间大小不同:栈空间通常较小,由操作系统预先分配,Linux默认栈大小为8MB,Windows默认约1MB,可通过编译器参数调整,但上限较低;堆空间几乎不受限制,仅受限于系统虚拟内存大小(32位系统最大约3GB,64位系统可达几十TB)。(3)生长方向不同:栈的生长方向为向下生长(向低地址扩展),栈指针从高地址向低地址移动;堆的生长方向为向上生长(向高地址扩展),内存分配时从低地址向高地址申请(实际堆内存为离散的空闲块链表,逻辑上为向上生长)。(4)分配效率不同:栈分配由硬件级支持,有专门的栈指针寄存器,分配和释放仅需移动栈指针,时间复杂度为O(1),效率极高;堆分配由C++运行时库管理,需要遍历空闲内存块链表、调整块大小、处理碎片等,时间复杂度更高,效率低于栈。(5)存储内容不同:栈存储函数的局部变量、函数参数、返回地址、寄存器上下文等,函数返回后对应栈帧立即回收;堆可存储任意类型的数据,生命周期由程序员控制,直到主动释放。(6)安全性不同:栈越界会触发栈溢出(StackOverflow)错误,可能被利用进行栈溢出攻击;堆越界会破坏堆内存的管理结构,导致程序崩溃、数据损坏或堆溢出攻击。2.请详细说明C++中的多态是什么,实现机制是什么?【答案解析】多态是面向对象编程的三大核心特性之一,指同一接口可以根据调用对象的不同执行不同的行为,本质是“一个接口,多种实现”。C++中的多态分为两类:(1)静态多态(编译期多态)在编译阶段即可确定调用的具体函数,也称为早绑定,实现方式包括:函数重载:同一作用域内函数名相同、参数列表不同的多个函数,编译期根据参数类型、个数、顺序匹配对应的函数。运算符重载:自定义运算符的行为,本质也是函数重载。模板(泛型编程):编译期根据传入的类型参数生成对应版本的代码,实现通用逻辑。(2)动态多态(运行期多态)程序运行时根据对象的实际类型确定调用的函数,也称为晚绑定,即通常所说的“多态”。实现条件:①基类中声明虚函数(virtual关键字修饰);②派生类重写(override)基类的虚函数;③通过基类指针或基类引用指向派生类对象,调用虚函数。实现机制:依赖虚函数表(vtable)和虚表指针(vptr)实现:1.每个包含虚函数的类都有一张虚函数表(属于类级别,每个类仅一份),表中存储该类所有虚函数的地址。派生类继承基类后,若重写了某个虚函数,会用自身的虚函数地址覆盖虚表中对应基类虚函数的地址;未重写的虚函数保留基类的地址。2.每个类的对象中都包含一个虚表指针(vptr),指向所属类的虚函数表。vptr在对象构造阶段由构造函数初始化,析构阶段会被修改为当前类的虚表。3.当通过基类指针调用虚函数时,程序会通过对象的vptr找到对应类的虚表,再从虚表中查找对应的函数地址并执行,从而实现运行时的动态绑定。补充说明:构造函数和析构函数中调用虚函数不会触发动态多态,因为构造时对象未完全初始化,析构时派生类部分已销毁,vptr仅指向当前类的虚表。3.请简述C++中的四种强制类型转换,分别说明其作用和使用场景。【答案解析】C++提供了四种功能明确、安全性更高的强制类型转换运算符,替代C风格的模糊转换,分别为static_cast、dynamic_cast、const_cast、reinterpret_cast:(1)static_cast(静态转换)作用:编译期进行类型检查,用于隐式转换允许的相关类型转换,不做运行时检查。适用场景:①基本数据类型之间的转换,如int转double、char转int等;②基类与派生类之间的指针/引用转换:上行转换(派生类指针/引用转基类)是安全的;下行转换(基类指针/引用转派生类)没有运行时检查,不安全,需程序员自行保证合法性;③void*指针与其他类型指针的转换;④空指针转换为目标类型的指针。不适用场景:不能去除const/volatile属性,不能转换不相关类型的指针(如int*转double*)。(2)dynamic_cast(动态转换)作用:运行期进行类型安全检查,仅用于多态类型的基类与派生类之间的转换,依赖RTTI(运行时类型信息)。适用场景:①下行转换(基类指针转派生类指针):转换成功返回目标类型指针,失败返回nullptr;②引用转换:转换成功返回目标类型引用,失败抛出std::bad_cast异常;③要求基类至少包含一个虚函数(否则编译报错)。特点:安全性高,但运行时检查会带来一定性能开销。(3)const_cast(常量转换)作用:用于修改类型的const或volatile属性,仅能作用于指针或引用,不能修改基本类型的const属性。适用场景:①去除const属性:当函数参数为非const指针/引用,但实际传入的对象是非const的,仅因上下文被const修饰时,可通过const_cast去除const以适配函数参数(若原对象本身是const的,转换后修改值属于未定义行为);②添加const属性:将非const指针/引用转换为const指针/引用。(4)reinterpret_cast(重解释转换)作用:最底层、最不安全的转换,直接对内存的二进制位进行重新解释,不做任何类型检查。适用场景:仅用于极低层级的转换,使用需极其谨慎,例如:①指针与整数类型之间的转换(如将指针存储为整数ID,再转回指针);②不同类型指针之间的转换(如int*转char*);③函数指针与数据指针之间的转换。与C风格转换相比,C++的四种转换语义更明确,便于代码阅读和问题排查,且安全性更高。4.请简述std::vector的底层实现,以及push_back的实现过程,为什么要成倍扩容而不是固定大小扩容?【答案解析】std::vector是STL中最常用的顺序容器,底层为连续动态数组,支持随机访问。(1)底层实现vector通过三个指针(迭代器)管理内存空间:_First:指向数组的起始位置(第一个已构造元素的地址);_Last:指向最后一个已构造元素的下一个位置;_End:指向整个数组容量的末尾位置。其中,size()返回值为_Last-_First(已存储元素的数量),capacity()返回值为_End-_First(当前分配的内存可容纳的最大元素数量)。(2)push_back的实现过程向vector末尾添加元素时,流程如下:①容量检查:若_Last!=_End(仍有剩余容量),直接在_Last指向的位置构造新元素,然后_Last向后移动一位,操作完成。②扩容操作:若_Last==_End(容量已满),则执行扩容:a.申请新的连续内存空间,容量为原容量的一定倍数(GCC为2倍,VS为1.5倍,不同编译器实现不同,通常为1.5~2倍);b.迁移元素:C++11及以后,若元素的移动构造函数声明为noexcept,则使用移动构造将旧元素迁移到新内存(提升效率且保证异常安全);否则使用拷贝构造(避免移动抛异常导致旧数据损坏);c.释放旧内存:依次销毁旧内存中的元素,释放旧的内存空间;d.更新指针:将_First、_Last、_End三个指针更新为指向新内存的对应位置;e.在新数组的_Last位置构造新元素,_Last向后移动一位。(3)成倍扩容的原因(均摊时间复杂度优化)若采用固定大小扩容(如每次扩容增加N个元素),插入n个元素时,扩容次数为n/N次,每次扩容需要拷贝当前所有元素,总拷贝次数为N+2N+3N+...+(n/N)*N=O(n²),均摊到每个元素的插入时间复杂度为O(n)。若采用成倍扩容(如2倍),插入n个元素时,扩容次数为log₂n次,总拷贝次数为1+2+4+8+...+n/2=n-1,总时间复杂度为O(n),均摊到每个元素的插入时间复杂度为O(1),性能远高于固定大小扩容。扩容倍数选择1.5~2倍是时间与空间的权衡:倍数过高会导致更多的内存浪费,倍数过低会导致频繁扩容,增加拷贝开销。5.请说明C++11中有哪些重要的新特性,至少列举8个并简要说明。【答案解析】C++11是C++标准的重大更新,标志着“现代C++”的开端,核心新特性如下:(1)自动类型推导:引入auto和decltype关键字,auto可根据初始化表达式自动推导变量类型,简化冗长的类型声明;decltype可获取表达式的类型,常用于模板编程中推导返回值类型。(2)右值引用与移动语义:右值引用(&&)可绑定到临时对象(右值),移动语义通过转移对象的资源所有权(如堆内存、文件句柄)避免不必要的深拷贝,大幅提升性能;std::move可将左值转换为右值引用,触发移动操作。(3)智能指针:引入std::shared_ptr、std::unique_ptr、std::weak_ptr三种智能指针,基于RAII机制管理动态内存,自动释放资源,避免内存泄漏;shared_ptr采用引用计数管理共享对象,weak_ptr用于解决shared_ptr的循环引用问题。(4)lambda表达式:匿名函数,可捕获上下文变量,简化STL算法的回调逻辑,支持值捕获、引用捕获、隐式捕获等多种捕获方式,提升代码可读性。(5)范围for循环:提供for(auto&x:container)语法,可直接遍历容器、数组、初始化列表等,简化遍历代码,避免迭代器使用错误。(6)nullptr:类型安全的空指针常量,替代C风格的NULL宏(NULL本质是整数0,存在函数重载匹配歧义),nullptr的类型为std::nullptr_t,可隐式转换为任意指针类型,不会匹配整数参数。(7)constexpr常量表达式:允许变量、函数在编译期计算结果,提升程序运行效率,可用于定义常量、数组大小、模板参数等。(8)final与override关键字:final修饰类时禁止被继承,修饰虚函数时禁止被派生类重写;override修饰派生类虚函数时,显式表明该函数重写了基类虚函数,编译器会检查重写的合法性,避免因参数列表、const属性不匹配导致的隐式未重写问题。(9)初始化列表:引入std::initializer_list,支持用花括号{}初始化对象、容器,语法更统一;类可定义接受initializer_list的构造函数,支持列表初始化。(10)线程支持库:原生提供std::thread、std::mutex、std::condition_variable、std::future等多线程组件,无需依赖第三方库,提升了多线程代码的跨平台性。编程题(共3题)1.字符串反转单词顺序题干:输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变,单词之间用单个空格分隔,句子首尾没有空格。例如输入字符串"Iamastudent",输出"studentaamI"。要求空间复杂度为O(1)(允许修改输入字符串)。【答案解析】解题思路采用两次反转法,无需额外空间:①第一次反转:反转整个字符串,此时单词顺序反转,单词内部字符也反转;②第二次反转:遍历字符串,定位每个单词的起止位置,逐个反转单词内部字符,即可得到单词顺序反转、单词内部顺序不变的结果。代码实现```cppusingnamespacestd;stringreverseWords(strings){intn=s.size();//第一次反转:反转整个字符串reverse(s.begin(),s.end());intstart=0;//第二次反转:逐个反转每个单词for(intend=0;end<=n;++end){start=end+1;}}returns;}```复杂度分析时间复杂度:O(n),每个字符最多被交换两次(整体反转一次、单词反转一次),总操作次数为线性。空间复杂度:O(1),仅使用常数额外变量,直接修改输入字符串。2.合并两个有序链表题干:将两个升序链表合并为一个新的升序链表并返回,新链表由给定两个链表的所有节点拼接而成。链表节点定义如下:```cppstructListNode{intval;ListNode*next;ListNode():val(0),next(nullptr){}ListNode(intx):val(x),next(nullptr){}ListNode(intx,ListNode*next):val(x),next(next){}};```【答案解析】解题思路(迭代法)采用哑节点简化边界处理,双指针遍历两个链表,每次选择值更小的节点接入结果链表:①创建哑节点dummy作为结果链表的前驱节点,用curr指针跟踪结果链表的当前末尾;②同时遍历两个链表,比较当前节点的值,将较小的节点接到curr的next,然后curr和对应链表的指针都向后移动一位;③当其中一个链表遍历完成后,将另一个链表的剩余部分直接接到curr的next;④返回dummy.next即为合并后的链表头节点。代码实现```cppListNode*mergeTwoLists(ListNode*list1,ListNode*list2){//哑节点,简化头节点处理ListNode*dummy=newListNode(-1);ListNode*curr=dummy;//遍历两个链表,选择较小的节点接入while(list1!=nullptr&&list2!=nullptr){if(list1->val<=list2->val){curr->next=list1;list1=list1->next;}else{curr->next=list2;list2=list2->next;}curr=curr->next;}//接入剩余未遍历的链表curr->next=(list1==nullptr)?list2:list1;returndummy->next;}```补充:递归法递归思路更简洁,但会产生递归栈开销:```cppListNode*mergeTwoLists(ListNode*list1,ListNode*list2){if(list1==nullptr)returnlist2;if(list2==nullptr)returnlist1;if(list1->val<=list2->val){list1->next=mergeTwoLists(list1->next,list2);returnlist1;}else{list2->next=mergeTwoLists(list1,list2->next);returnlist2;}}```复杂度分析时间复杂度:O(n+m),n和m为两个链表的长度,每个节点仅被遍历一次。空间复杂度:迭代法为O(1),仅使用常数指针;递归法为O(n+m),递归栈深度最大为两个链表总长度。3.最长公共子序列题干:给定两个字符串text1和text2,返回两个字符串的最长公共子序列的长度,若不存在公共子序列则返回0。子序列的定义为:原字符串删除部分或全部字符、不改变剩余字符相对顺序得到的新字符串。例如text1="abcde",text2="ace",最长公共子序列为"ace",长度为3。【答案解析】解题思路(动态规划)这是经典的二维动态规划问题,定义dp[i][j]表示text1的前i个字符与text2的前j个字符的最长公共子
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026银行远程营销面试题目及答案
- 2026应急能力面试题及答案
- 2026齿轮技术面试题及答案解析
- 晋升副主任医师个人专业技术工作总结
- 小学五年级信息科技《Scratch创意编程-涂色小火箭》教学设计
- 初中地理七年级下册《澳大利亚的自然环境与经济发展》教学设计
- 初中七年级德育《合理饮食 护航成长》主题班会教学设计
- 八年级语文《散文两篇》教学设计(暑期预习)
- 初中九年级地理中考专题复习课教学设计:成因分析类综合题的破题逻辑与表达规范
- 初中体育与健康八年级《体育精神》教学设计
- 第8课(斜捺) 课件-【知识精研】小学生书法版一年级
- 高一化学-学习·探究·诊断(必修1)(西城学探诊)
- 供货产品应急预案
- 生化课展示-生物素作业幻灯片课件
- 先进制造技术 课件 第一章 先进制造技术概论
- 消费者行为学课件
- 铁路应急救援培训课件
- YY/T 0456.3-2014血液分析仪用试剂第3部分:稀释液
- WS/T 494-2017临床定性免疫检验重要常规项目分析质量要求
- GH/T 1072-2011籽棉货场安全技术规范
- GB/T 3216-2016回转动力泵水力性能验收试验1级、2级和3级
评论
0/150
提交评论