zoukankan      html  css  js  c++  java
  • 软件测试基础

    什么是软件测试?

    顾名思义,就是对软件进行测试的意思!

    这篇文章就和大家一起来学习一下软件测试的基础知识吧!

    一、了解软件测试的相关概念、发展史等基础知识

    概念:软件测试就是用人工和自动化的手段来运行和测试某个软件系统的过程。

    目的:通过对软件的各种测试来检验该软件是否满足用户的需求或是弄清预期结果和实际结果之间的差别。

    软件测试的发展史,见下图

     

    在一个软件项目中软件测试到底有什么用处呢?软件测试人员存在的意义是什么呢?

    软件测试人员进行软件测试工作有很多用处,下面列举几点:

    1. 尽早介入发现缺陷,减少返工,降低开发维护成本
    2. 持续改进进程、帮助需求定义和设计
    3. 提高客户满意度、扩大市场份额
    4. 对产品质量完成全面评估,为产品的发布、部署、鉴定、决策者提供信息
    5. 预防缺陷,通过缺陷分析和原因总结,规避后续同类型缺陷的产生再犯

     

    二、软件的生命周期

    需求调研阶段--需求分析阶段--软件设计阶段--编码开发阶段--软件测试阶段--软件发布上线--软件运行和维护阶段--软件下线

     

    三、软件开发项目组成员

     

    四、软件测试的基本原则

    1. 测试是上下文相关的(对不同软件的类型、用途,测试要求不一样)
    2. 穷尽测试是不可能的(尽量测可能发现问题)
    3. 测试尽早介入(降低维护成本)
    4. 杀虫剂悖论(每个版本的测试用例都一样的话可能发现不了其它的bug每个版本都要适时的调整用例)
    5. 缺陷群集性(80%的缺陷可能群集在20%的模块里模块越复杂出现的缺陷可能就越多)
    6. 测试证明存在缺陷(测试用来证明系统存在BUG,不是为了证明系统不存在BUG,BUG可能是潜在的,还没达到暴露的条件)
    7. 无措谬论(说一个系统没有错是不对的)

     

    五、软件测试的对象

     

    六、软件开发模型

    1. 瀑布模型

    即从上到下的模型,每个环节结束了才可以开始下一个环节
    特点 :对每一个环节的输出文档质量要求比较高
    缺点:后期一旦发现问题,维护成本比较高

    2. 原型模型

    类似瀑布模型,相比较瀑布模型,在需求分析阶段会有输出物:原型设计(软件的原型设计图),交与客户后,客户确定没有问题后才开始后续工作
    特点:重点关注原型图的设计
    缺点:需求分析阶段后的阶段的输出文档质量要求没有瀑布模型高,人员出现变动时会增加后期的软件维护成本

    3. 敏捷模型

    是一种以人为核心、迭代、循序渐进的开发方法(目前主流的开发模型)先根据重要的需求发布一个原始版本,再制定版本迭代计划,不断迭代版本。

    特点:不要求所有文档的质量都达到CMMI认证标准

    每日立会(站立会):1汇报一下工作进度、2遇到的问题和解决的办法、3今日的任务计划
    评审会:评审软件是否满足用户需求
    反思会:总结工作,总结经验和教训
    如果一个项目启用的是敏捷模型,那么开发人员和测试人员就属于一个产品线,不分开发部门、测试部门,开发、测试都会进行相应的测试,开发人员测试自己代码,测试人员测试环境、功能、性能等

     

    研发的其它模型:

    螺旋模型:适用于大型复杂软件系统
    RUP模型(Rational Unified Process):模型过于复杂,难于掌握,耦合度高不适合

     

    七、软件测试模型

    1. V模型

    概设--->使用什么方法设计、软件的整体架构等
    详设--->具体的方法、思路
    编码--->编写实现软件功能点的代码
    单元测试--->大多由开发本人完成(测试代码本身)
    集成测试--->在单元测试的基础上,测试模块与模块之间、模块与第三方接口之间的功能是否满足需求,依赖详细设计
    系统测试--->验证非功能特性(硬件、系统兼容性、与当前系统中其他软件的兼容性),依赖概要设计
    验收测试--->交由用户验证,依赖用户需求

    优点:既包括低层测试有包括了高层测试,低层测试是为了源代码的正确性,高层测试是为了使整个系统满足用户的需求
    局限性:把测试过程作为在需求分析、概要设计、详细设计及编码之后的一个阶段,不能尽可能早的介入测试,积压测试和开发修改缺陷的工作量。

     

    2. W模型(双V模型,目前的主流测试模型)

    第一个V代表开发和实现阶段,第二个V是跟踪测试阶段(测试每个阶段的产出物)
    需求分析阶段---需求测试(检查需求文档本身有没有问题,保证对需求的历届一致)
    概要设计---概要设计测试(需求评审、设计评审)
    详细设计---详细设计测试
    编码实现---单元测试
    模块集成---集成测试
    系统构建---系统测试
    系统安装---验收测试

    优点:
    1.如果测试文档能尽早提交,那么就有了更多的检查和检阅的时间,这些文档还可用于评估开发文档。
    2.测试者可以在项目中尽可能早地面对规格说明书中的挑战。
    3.测试还可以尽可能早地找出缺陷所在,从而帮助改进项目内部的质量。

    局限性:无法支持迭代、自发性以及变更调整

     

    3. H模型

    优点:
    1.软件测试不仅仅指测试的执行,还包括很多其他的活动。
    2.软件测试是一个独立的过程,贯穿产品整个生命周期,与其他流程并发地进行。
    3.软件测试要尽早准备,尽早执行。
    4.软件测试是根据被测物的不同而分层次进行的。
    5.不同层次的测试活动可以是按照某个次序先后进行的,但也可能是反复的。

     

    4. X模型

     

    5. 前置模型

    优点:
    1.体现开发和测试相结合
    2.对每一个交付内容进行测试
    3.在设计阶段进行测试计划和测试设计
    4.测试和开发结合在一起
    5.让验收测试和技术测试保持相对独立

     

    八、软件测试阶段(按照时间节点)

    1. 需求测试

    返工:70%~85%的原因由于需求有问题
    重点:检查软件需求规格说明书(SRS)
    SRS标准
    a. 完整性(尽可能完整的描述用户需求)
    b. 正确性(正确描述用户需求)
    c. 一致性(用户、开发、测试理解需求一致)
    d. 可行性(需求是不是可以实现)
    e. 无二义性
    f. 健壮性
    g. 必要性(确定需求是否必要)
    h. 可测试性(明确测试正确的标准)
    i.可修改性(软件功能本身有没有可维护性)

     

    2. 单元测试

    单元:函数、类
    单元测试是针对软件基本组成单元(软件设计的最小单位)来进行正确性检验的测试工作
    单元测试的目的是检验软件模块对 详细设计说明书(LLD)的符合程度

     

    3. 集成测试

    集成测试是对单元之间及单元与第三方接口之间的测试,目的是验证接口是否与设计相符,是否与需求相符。(即检测软件模块对《概要设计说明书》的符合程度)

    集成策略:自底向上或自顶向下 渐增式

    自底向上:先检测 被调用模块 的功能,如果没有问题,再使用 调用模块 调用 被调用模块(当我们调用 被调用模块 进行集成测试时我们必须要自己开发一个 驱动模块 来调用没有问题的 被调用模块)

    自顶向下:先测 调用模块 的功能,如果没有问题,才可以调用 被调用模块(我们需要自己开发桩,检测能不能调用到别人)

     

    4. 系统测试

    系统测试是将已经集成好的软件系统,作为整个基于计算机系统的一个元素,与计算机硬件、外设、某些支持软件、数据和人员等其他系统元素结合在一起,在实际运行(使用)环境下,对计算机系统进行一系列的测试工作
    系统测试的目的在于通过与《需求规格说明书》作比较,发现软件与系统需求定义不符合或与之矛盾的地方。

     

    5. 确认测试

    又称有效性测试,他的任务是验证软件的有效性,即验证软件的功能和性能及其它特性是否与用户的要求一致。若能达到这一要求,则表明开发的软件是合格的。

     

    6. 验收测试

    交付用户部署前,进行验收测试以用户为主,验收组:项目组成员、用户代表或者系统的其它利益相关者。根据合同、《需求规格说明书》或《验收测试计划》对成品进行验收测试。

     

    7. Alpha测试和Beta测试

    Alpha测试:内部,模拟/真实(例如:游戏软件)

    Beta测试:外部,真实

     

    8. UAT测试

    User Acceptance Test 用户接受测试

    目的:验证系统的可用性,测试用户的接受程度

     

    回归测试

    软件在测试或其他活动中发现的缺陷经过修改后进行的测试

    目的:验证缺陷得到了正确的修复,同时保证对系统的变更没有影响之前的功能

    特点:可以发生在测试的任何一个阶段,包括单元测试、集成测试、系统测试(贯穿整个测试过程)

    回归测试的策略:
    1. 完全重复测试:重新执行所有在前期测试阶段建立的测试用例,来确认问题修改的正确性和修改的扩散局部影响性
    2. 选择性重复测试: 即有选择地重新执行部分在前期测试阶段建立的测试用例,来测试被修改的程序

     

    回归测试的方法:

    1. 覆盖修改法:即针对被修改的部分,选取或重新构造测试用例验证没有错误再次发生的用例选择方法
    2. 周边影响法:该方法不但要包含覆盖修改法确定的用例,还需要分析修改的扩散影响,对那些受到修改间接影响的部分选择测试用例验证它没有收到不良影响。该方法比覆盖修改法更充分一点
    3. 指标达成方法:这是一种类似于单元测试的方法,在重新执行测试前,先确定一个要达成的指标,如修改部分代码100%的覆盖、与修改有关的接口60%的覆盖等,基于这种要求选择一个最小的测试用例集合

     

    回归测试的流程:

    以下流程适合于单元测试、集成测试和系统测试
    1、在测试策略制定阶段,制定回归测试策略
    2、确定需要回归测试的版本
    3、回归测试版本发布,按照回归测试策略执行回归测试
    4、回归测试通过,关闭缺陷跟踪单(问题单)
    5、回归测试不通过,缺陷跟踪单返回开发人员,开发人员重新修改问题
    6、再次提交测试人员回归测试

     

    回归测试的自动化:

    (1)回归测试是一个重用以前成果的测试,很难预料到要经过多少次回归系统才能达到满意的水平,结果,这种回归测试将可能演变成一种重复的、令人心烦意乱的工作,效果与人员的积极性将大打折扣,因此,在回归测试道路上的动化便是我们工作的追求
    (2)回归测试的自动化法包括测试程序的自动运行、自动配置,测试用例的管理和自动输入,测试的自动执行,测试信息与结果的自动采集,测试结果的自动比较和结论的自动输出,尤其前面提到的各类数据的共享决策
    (3)对系统测试功能比较简单、测试界面相对稳定并且测试用例良好组织的测试来说,采用“捕捉回放”工具是比较合适的,这类工具有Selenium等

    自动化代替部分手工测试的工作

     

    冒烟测试

    概念:对每一个新编译的需要正式测试的软件版本进行简单的功能测试的过程

    测试对象:每一个新编译的需要正式测试的软件版本

    测试目的:确认软件基本功能正常,可以进行后续的正式测试工作

     

    九、软件的测试类型

    1. 功能测试

    概念:功能测试是根据产品的需求规格说明书和测试需求列表,验证产品的功能实现是否符合产品的需求规格
    目标:为了发现以下几类错误:
    是否有不正确或遗漏了的功能
    功能实现是否能满足用户需求和系统设计的隐藏需求?
    输入能否正确接受?能否正确输出结果?

     

    2. 性能测试

    概念:用来测试软件在集成系统中的运行性能
    目标:度量系统相对于预定义目标的差距
    性能测试必须要有工具支持,市场上有一些专门用于GUI或Web的性能测试工具:
    Loadrunner、Jmeter、SilkPerformer、WebLoad

    性能测试收集的信息
    CPU的使用情况
    IO使用情况
    内存使用情况
    信道使用情况
    每个模块执行时间的百分比
    一个模块等待IO完工的百分比
    指令随时间的跟踪路径

     

    3. 负载测试

    概念:超过了被测对象标准性能符合指标下,验证系统的负载承受能力。并要求超负荷情况下,依然能正常实现业务功能。负载测试是通过不断对被测对象施加负荷,观察被测对象在不同负载下的性能表现。

     

    4. 压力测试

    概念:调查系统在其资源超负荷的情况下的表现。尤其感兴趣的是这些对系统的处理时间有什么影响。
    目标:通过极限测试方式,发现系统在极限或者恶劣环境中的自我保护能力。主要验证系统的可靠性,找到系统薄弱环节

     

    5. 容量测试(Volume Testing)

    容量测试(Volume Testing)的目的是使系统承受超额的数据容量来发现它是否能够正确处理。容量测试是面向数据的
    目的:为了显示系统可以处理目标内确定的数据容量。

    6. 安全性测试

    安全测试(Security Testing)用来验证集成在系统内的保护机制是否能够在实际中保护系统不受到非法的侵入。 用来保证系统本身数据的完整性和保密性。如当受到恶意攻击时,设备的自我保护能力,病毒防护能力,自定义通信协议安全性等。广义的还包括物理安全性测试、业务安全性测试。

     

    7. GUI测试(图形化界面测试)

    GUI测试主要针对的是系统软件GUI界面的测试

    GUI测试的主要内容:

    a. 界面实现与界面设计的吻合情况

    b. 确认界面处理的正确性

    GUI测试的对象:

    简单界面元素:指功能和属性相对比较单一的界面区域,即通常所指的各种控件
    组合类界面元素:主要指一些复杂的界面元素,比如工具栏,组合框,表格,菜单栏等
    完整界面(窗口):由一系列界面元素通过适当的形式组合而成的界面形式,最为常见的为各种窗口。包括各种对话框、单文档窗口、多文档父窗口,多文档子窗口等

    GUI自动化测试工具:QTP,SilkTest,QARun,QuickTestProfessional,Selenium

     

    8. 可用性测试

    可用性测试(Usability Testing)是为了检测用户在理解和使用系统方面到底有多好。主要考虑产品是否符合实际应用情况,是否符合用户习惯或特殊要求,操作方式是否方便合理、设备和用户间的交互信息是否准确易于理解、是否遵从行业习惯、外观/界面是否美观等。应涉及到所有和用户有交互的功能或子系统。这包括系统功能、系统发布、帮助文本和过程,以保证用户能够舒适地和系统交互。

     

    9. 安装卸载测试

    定义:系统的可安装性测试,主要是根据软件的测试特性列表、软件安装、配置文档,设计安装过程的测试用例,发现软件在安装过程中的错误

    目的:系统可安装性测试的目的不仅是找安装软件本身的错误,而且还要找安装文档的错误。在安装软件系统时,会有多种选择,要分配和装入文件与程序,布置适当的配置,进行程序的联结。而安装测试就要找出这些安装过程中出现的错误

     

    10. 异常测试

    概念:系统异常测试又叫系统容错和可恢复性测试,它是通过人工干预手段使系统产生软、硬件异常,通过验证系统异常前后的功能和运行状态,达到检验系统的容错、排错和恢复的能力。它是系统可靠性评价的重要手段
    容错处理:
    • 系统自动处理
    • 人工干预处理

    注意:
    • 系统异常测试还与系统的指标测试有关系,当系统需要提供的服务能力大于系统的设计指标时,也属于系统异常的情况,因此应该结合起来加以考虑
    • 系统的可靠性是设计出来的,而不是测试出来的。测试出来的数据有助于为我们进行进一步的系统优化设计积累经验,设计和测试是一个互为反馈的过程

     

    11. 文档测试

    文档测试(Documentation Testing)的目标是验证用户文档是正确的并且保证操作手册的过程能够正确工作。

     

    12. 网络测试

    概念:网络测试是在网络环境下和其他设备对接,进行系统功能、性能与指标方面的测试,保证设备对接正常

    内容:网络测试考察系统的处理能力、系统兼容性、系统稳定可靠性及用户使用等方面。如通信产品,主要进行

    协议测试:
    • 一致性测试:检测所实现的系统与协议规范符合程度
    • 性能测试:检测协议实体或系统的性能指标(数据传输率、联接时间,执行速度、吞吐量、并发数等)
    • 互操作性测试:检测同一协议不同实现厂商之间,同一协议不同实现版本之间、或同一类协议不同实现版本之间互通能力和互连操作能力
    • 坚固性测试:检测协议实体或系统在各种恶劣环境下运行的能力(信道被切断、通信设备掉电、注入干扰报文等)

     

    13. 稳定性测试

    系统稳定性测试目的是评价系统在一定负荷情况下、长时间的运行情况。包括系统在一定负荷下,再增加新的业务,原有的业务是否受影响,新的业务是否能正常工作,系统资源有无泄漏,数据有无不一致的情况,系统性能是否会降下来,关键点是长时间的运行后,系统的状况如何,系统平均无故障时间MTBF是否满足系统设计要求。
    系统的平均无故障时间(MTBF)越长越好,平均故障修复时间(MTTR)越短越好

     

    14. 兼容性测试

    兼容性测试验证被测对象与硬件、其他软件之间的兼容性

     

    十、软件测试的方法

    1. 白盒测试

    • 白盒测试是依据被测软件分析程序内部构造,并根据内部构造设计用例,来对内部控制流程进行测试,可完全不顾程序的整体功能实现情况。
    • 白盒测试是基于程序结构的逻辑驱动测试。
    • 白盒测试又可以被称为玻璃盒测试、透明盒测试、开放盒测试、结构化测试、逻辑驱动测试。

     

    白盒测试示意图

     

     白盒测试的优点:

    • 白盒测试一般在测试前期进行,通过达到一定的逻辑覆盖率指标,使得软件内部逻辑控制结构上的问题能基本得到消除
    • 白盒测试能保证内部逻辑结构达到一定的覆盖程度,能够给予软件代码质量更大的保证
    • 白盒测试发现问题后解决问题的成本较低

     

    白盒测试常用的技术

    • 静态分析:控制流分析、数据流分析、信息流分析等
    • 动态分析:逻辑覆盖测试(分支测试、路径测试等)、程序插装等
    逻辑覆盖方法:语句覆盖、判定覆盖、条件覆盖、判定条件覆盖、条件组合覆盖、路径覆盖

     

    2. 黑盒测试

    • 黑盒测试把被测对象看成一个黑盒,只考虑其整体特性,不考虑其内部具体实现。
    • 黑盒测试针对的被测对象可以是一个系统、一个子系统、一个模块、一个子模块、一个函数等。
    • 黑盒测试又可以被称为基于规格的测试。

     

    黑盒测试示意图

    常见的黑盒测试的类型

    • 功能性测试,一种是顺序测试每个程序特性或功能,另一种途径是一个模块一个模块的测试,即每个功能在其最先调用的地方被测试;
    • 容量测试,检测软件在处理海量数据时的局限性,能发现系统效率方面的问题;
    • 负载测试,检测系统在一个很短时间内处理一个巨大的数据量或执行许多功能调用上的能力;
    • 恢复性测试,主要保证系统在崩溃后能够恢复外部数据的能力

     

    黑盒测试的优点:

    黑盒测试要求没有白盒测试高
    • 对于更大的代码单元来说(子系统甚至系统级)比白盒测试效率要高;
    • 测试人员不需要了解实现的细节,包括特定的编程语言;
    • 从用户的视角进行测试,很容易被大家理解和接受;
    • 有助于暴露任何规格不一致或有歧义的问题

    3. 灰盒测试(结合白盒和黑盒测试)

    • 根据利用的被测对象信息的不同,会采用不同的方法进行测试。
    • 利用被测对象的整体特性信息,采用黑盒测试方法
    • 利用被测对象的内部具体实现信息,采用白盒测试方法
    • 如果既利用被测对象的整体特性信息,又利用被测对象的内部具体实现信息,采用的就是灰盒测试方法。两种信息占的比例不同,相应的灰度就不同。完全是整体特性信息,就是黑盒测试,完全是内部具体实现信息,就是白盒测试
    • 典型的灰盒测试比如集成测试和系统测试时借助log信息

     

    4. 静态测试

    静态测试:不运行被测试的软件系统,而是采用其他手段和技术对被测试软件进行检测的一种测试技术。例如:代码走读(指读代码本身,很多项目组都要求)、文档评审、程序分析等都是静态测试的范畴。常用技术有静态分析技术。

    静态分析技术:

    • 定义:静态分析是一种不通过执行程序而分析程序执行的技术
    • 功能:检查软件的表示和描述是否一致,没有冲突或者没有歧义,
    它瞄准的是纠正软件系统在描述、表示和规格上的错误,因此是任
    何进一步测试执行的前提。
    主要有三种不同的程序测试可能性:
    • 考虑程序是否满足编码规则,语法上是否具有一致性和完整性;(语法通常会加注释,方便理解的一致性,方便后期维护)
    • 考虑文档(需求文档、设计文档)描述是否规范、准确、便于查阅;
    • 考虑程序和文档之间的一致性。

     

    5. 动态测试

    动态测试(用到的较多): 按照预先设计的数据和步骤去运行被测软件系统,从而对被测软件系统进行检测的一种测试技术。常用技术有动态分析技术。

     

    6. 人工和自动化测试

    • 人工测试(市面上大多还是人工测试):测试活动(如评审、测试设计、测试执行等)由人来完成,狭义上是指测试执行由人工完成,这是最基本的测试形式
    • 自动化测试:一般是指通过计算机模拟人的测试行为,替代人的测试活动,狭义上是指测试执行由计算机来完成

     

    自动化测试的意义

    • 对程序新版本运行前一版本执行的测试,提高回归测试效率
    • 可以运行更多更频繁的测试,比如冒烟测试
    • 可以执行手工测试困难或不可能做的测试,比如大量的重复操作或者集成测试
    • 更好地利用资源,比如测试仪器或者被测对象

    举例: 测试服务器可能性能较差,下班后打开自动化测试脚本,自动测试,第二天查看结果

     

    自动化测试的限制

    • 不能取代手工测试,自动化测试只能提高测试效率,不能提高测试有效性,即不可能发现更多缺陷

    • 手工测试比自动测试发现的缺陷更多

    • 对测试设计依赖性极大,测试设计的不好会遗漏问题

    • 自动化测试对软件开发具有很大的依赖性,开发上出现变更可能导致前面的自动化测试完全失效

    • 工具本身并不具备想象力,工具不具有智能

    通常不建议使用自动化来进行版本回归测试

     

    十、软件测试的流程

    1. 测试计划阶段--测试计划(测试范围、测试时间、哪些人来做、资源:工具等 由测试leader来编写)

    2. 测试设计阶段--测试方案(指导测试人员怎么执行测试工作、测试过程中用到哪些测试工具)

    3. 测试实现阶段--测试用例(测试人员重要的产出物)、测试规程(测试工作的规则和章程)

    4. 测试执行阶段--缺陷报告(和开发沟通,让开发解决BUG)、测试报告(包含测试结果文档)

     

    主要的测试文档
    1. 测试计划:指明测试范围、方法、资源,以及相应测试活动的时间进度安排表的文档。
    2. 测试方案:指明为完成软件或软件集成特性的测试而进行的设计测试方法的细节文档。
    3. 测试用例:指明为完成一个测试项的测试输入、预期结果、测试执行条件等因素的文档。(由测试人员编写)
    4. 测试规程:指明执行测试时测试活动序列的文档。
    5. 缺陷报告:根据测试结果提供缺陷报告,一般有专门收集缺陷报告的工具(如:禅道)
    6. 测试报告:指明执行测试结果的文档。(测了多少用例,发现了多少BUG)
    7. 测试日报:每天测试执行情况的记录和总结。

     

    系统测试各阶段的输入和输出

    测试工程师系统测试各阶段任务
    1. 软件需求阶段:评审软件需求规格说明书
    2. 软件设计阶段:评审软件概要设计说明书、软件详细设计说明书、协助编写系统测试计划
    3. 软件编码阶段:设计系统测试用例、准备测试资源(测试工具、测试环境等)、开发测试脚本、开发测试工具、准备测试数据(其中开发测试脚本、开发测试工具不一定有,但是准备测试数据是一定有的)
    4. 软件测试阶段:执行测试用例、提交缺陷单、跟踪缺陷、回归测试、提交测试报告

     

    软件测试QC|与QA(质量保证 Quality Assurance)的区别
    1. 从性质上看:测试属于技术的工作,QA属于管理的工作
    2. 从对象上看:测试的对象是软件研发产品,大多数工作是对研发领域的检验,QA的对象是对软件的整个过程,覆盖各个领域
    3. 从手段上看:测试以事后检查为主,QA强调的是缺陷预防
    QA检查QC在什么时间节点有没有按照公司规范完成相应的任务要求
    QA从测试一开始就开始监督QC工作了
    QA的目的是预防QC在测试过程中发生错误

  • 相关阅读:
    Java vs Python
    Compiled Language vs Scripting Language
    445. Add Two Numbers II
    213. House Robber II
    198. House Robber
    276. Paint Fence
    77. Combinations
    54. Spiral Matrix
    82. Remove Duplicates from Sorted List II
    80. Remove Duplicates from Sorted Array II
  • 原文地址:https://www.cnblogs.com/Ceslie-zhang/p/8544001.html
Copyright © 2011-2022 走看看