浅谈软件研发工程师(Java)面试

Java基础

1.Java和JavaSciprt

概念

  • Java 是原Sun公司推出的面向对象的程序设计语言,特别适合于互联网应用程序开发;
  • JavaScript是Netscape公司的产品,为了扩展Netscape浏览器的功能而开发的一种可以嵌入Web页面中运行的基于对象和事件驱动的解释性语言。

基于对象和面向对象

  • Java是一种真正的面向对象的语言,即使是开发简单的程序,必须设计对象;
  • JavaScript是种脚本语言,它可以用来制作与网络无关的,与用户交互作用的复杂软件。
  • JavaScript是一种基于对象(Object-Based)和事件驱动(Event-Driven)的编程语言,因而它本身提供了非常丰富的内部对象供设计人员使用。

解释和编译

  • Java的源代码在执行之前,必须经过编译。
  • JavaScript是一种解释性编程语言,其源代码不需经过编译,由浏览器解释执行。(目前的浏览器几乎都使用了JIT(即时编译)技术来提升JavaScript的运行效率)

强类型变量和类型弱变量

  • Java采用强类型变量检查,即所有变量在编译之前必须作声明;
  • JavaScript中变量是弱类型的,甚至在使用变量前可以不作声明,JavaScript的解释器在运行时检查推断其数据类型。

2.构造函数?

什么是构造函数?

  • 当新对象被创建的时候,构造函数会被调用。每一个类都有构造函数。在程序员没有给类提供构造函数的情况下,Java编译器会为这个类创建一个默认的构造函数。

构造函数重载

  • Java中构造函数重载和方法重载很相似。可以为一个类创建多个构造函数。每一个构造函数必须有它自己唯一的参数列表。

复制构造函数

  • Java不支持像C++中那样的复制构造函数,这个不同点是因为如果你不自己写构造函数的情况下,Java不会创建默认的复制构造函数。

3.方法覆盖和方法重载

方法重载(Overloading)

  • Java中的方法重载发生在同一个类里面两个或者是多个方法的方法名相同但是参数不同的情况。

方法覆盖(Overriding)

  • 方法覆盖是说子类重新定义了父类的方法。方法覆盖必须有相同的方法名,参数列表和返回类型。覆盖者可能不会限制它所覆盖的方法的访问。

4.abstract class和interface的区别

抽象类

  • 声明方法的存在,而不去实现它的类被叫做抽象类(abstract class),它用于要创建一个体现某些基本行为的类,并为该类声明方法,但不能在该类中实现该类的情况。
  • 不能创建abstract 类的实例。然而可以创建一个变量,其类型是一个抽象类,并让它指向具体子类的一个实例。
  • 不能有抽象构造函数或抽象静态方法。
  • Abstract 类的子类为它们父类中的所有抽象方法提供实现,否则它们也是抽象类为。取而代之,在子类中实现该方法。知道其行为的其它类可以在类中实现这些方法。

接口

  • 接口(interface)是抽象类的变体。
  • 在接口中,所有方法都是抽象的。
  • 多继承性可通过实现这样的接口而获得。
  • 接口中的所有方法都是抽象的,没有一个有程序体。
  • 接口只可以定义static final成员变量。
  • 接口的实现与子类相似,除了该实现类不能从接口定义中继承行为。
  • 由于有抽象类,它允许使用接口名作为引用变量的类型。通常的动态联编将生效。
  • 引用可以转换到接口类型或从接口类型转换,instanceof 运算符可以用来决定某对象的类是否实现了接口。

5.Overload和Override的区别

  • 方法的重写Overriding和重载Overloading是Java多态性的不同表现。
  • 重写Overriding是父类与子类之间多态性的一种表现重载Overloading是一个类中多态性的一种表现。
  • 如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写(Overriding)。子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被”屏蔽”了。
  • 如果在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型,则称为方法的重载(Overloading)。
  • Overloaded的方法是可以改变返回值的类型。

6.面向对象三大特征

封装

  • 封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面。
  • 面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。

继承

  • 继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法。
  • 对象的一个新类可以从现有的类中派生,这个过程称为类继承。
  • 新类继承了原始类的特性,新类称为原始类的派生类(子类),而原始类称为新类的基类(父类)。
  • 派生类可以从它的基类那里继承方法和实例变量,并且类可以修改或增加新的方法使之更适合特殊的需要。

多态

  • 多态性是指允许不同类的对象对同一消息作出响应。
  • 多态性包括参数化多态性和包含多态性。
  • 多态性语言具有灵活、抽象、行为共享、代码共享的优势,很好的解决了应用程序函数同名问题。

7.接口和抽象类的区别

  • 接口中所有的方法隐含的都是抽象的。而抽象类则可以同时包含抽象和非抽象的方法。
  • 类可以实现很多个接口,但是只能继承一个抽象类。
  • 类可以不实现抽象类和接口声明的所有方法,当然,在这种情况下,类也必须得声明成是抽象的。
  • 抽象类可以在不提供接口方法实现的情况下实现接口。
  • Java接口中声明的变量默认都是final的。抽象类可以包含非final的变量。
  • Java接口中的成员函数默认是public的。抽象类的成员函数可以是private,protected或者是public。
  • 接口是绝对抽象的,不可以被实例化。抽象类也不可以被实例化,但是,如果它包含main方法的话是可以被调用的。

8.ArrayList、Vector、LinkedList的存储性能和特性

  • ArrayListVector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢。
  • Vector中的方法由于添加了synchronized修饰,因此Vector是线程安全的容器,但性能上较ArrayList差,因此已经是Java中的遗留容器。
  • LinkedList使用双向链表实现存储(将内存中零散的内存单元通过附加的引用关联起来,形成一个可以按序号索引的线性结构,这种链式存储方式与数组的连续存储方式相比,内存的利用率更高),按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快
  • Vector属于遗留容器(Java早期的版本中提供的容器,除此之外,Hashtable、Dictionary、BitSet、Stack、Properties都是遗留容器),已经不推荐使用.
  • 由于ArrayListLinkedListed都是非线程安全的,如果遇到多个线程操作同一个容器的场景,则可以通过工具类Collections中的synchronizedList方法将其转换成线程安全的容器后再使用(这是对装潢模式的应用,将已有对象传入另一个类的构造器中创建新的对象来增强实现)。

9.HashMap和Hashtable的区别

  • HashMap和Hashtable都实现了Map接口,因此很多特性非常相似
  • HashMap允许键和值是null,而Hashtable不允许键或者值是null。
  • Hashtable是同步的,而HashMap不是。因此,HashMap更适合于单线程环境,而Hashtable适合于多线程环境。
  • HashMap提供了可供应用迭代的键的集合,因此,HashMap是快速失败的。
  • 另一方面,Hashtable提供了对键的列举(Enumeration)。
  • 一般认为Hashtable是一个遗留的类。

Java 进阶

1 什么是线程池(thread pool)

  • 在面向对象编程中,创建和销毁对象是很费时间的,因为创建一个对象要获取内存资源或者其它更多资源。
  • Java虚拟机将试图跟踪每一个对象,以便能够在对象销毁后进行垃圾回收,所以提高服务程序效率的一个手段就是尽可能减少创建和销毁对象的次数,特别是一些很耗资源的对象创建和销毁,这就是”池化资源”技术产生的原因。
  • 线程池顾名思义就是事先创建若干个可执行的线程放入一个池(容器)中,需要的时候从池中获取线程不用自行创建,使用完毕不需要销毁线程而是放回池中,从而减少创建和销毁线程对象的开销。
  • Java 5+中的Executor接口定义一个执行线程的工具。它的子类型即线程池接口是ExecutorService。
  • 要配置一个线程池是比较复杂的,尤其是对于线程池的原理不是很清楚的情况下,因此在工具类Executors面提供了一些静态工厂方法,生成一些常用的线程池,如下所示.
  • newSingleThreadExecutor:创建一个单线程的线程池。这个线程池只有一个线程在工作,也就是相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执行。
  • newFixedThreadPool:创建固定大小的线程池。每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。
  • newCachedThreadPool:创建一个可缓存的线程池。如果线程池的大小超过了处理任务所需要的线程,那么就会回收部分空闲(60秒不执行任务)的线程,当任务数增加时,此线程池又可以智能的添加新线程来处理任务。此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小。
  • newScheduledThreadPool:创建一个大小无限的线程池。此线程池支持定时以及周期性执行任务的需求。
  • newSingleThreadExecutor:创建一个单线程的线程池。此线程池支持定时以及周期性执行任务的需求。

2 懒汉式和饿汉式对比

对比项 懒汉式 饿汉式
望文生义 非常懒,不到必要时候不创建单例实例 类加载时,就创建单例实例
线程安全(多线程环境下,能否确保对象只被创建一次) 不安全 安全
单例实例创建时机 当Singleton.getUniqueInstance()方法被调用时,才会创建实例。如果程序始终没有调用该方法,则单例实例永远不会被创建,节省了内存空间和资源。 在Singleton被类加载器加载时,创建单例实例对象,并且把单例对象一直存放在内存的方法区,直到程序结束才会把单例对象销毁。如果程序始终没有使用该对象,将会造成资源浪费

3 UML中有哪些常用的图?

  • UML定义了多种图形化的符号来描述软件系统部分或全部的静态结构和动态结构,包括:用例图(use case diagram)、类图(class diagram)、时序图(sequence diagram)、协作图(collaboration diagram)、状态图(statechart diagram)、活动图(activity diagram)、构件图(component diagram)、部署图(deployment diagram)等。
  • 在这些图形化符号中,有三种图最为重要,分别是:用例图(用来捕获需求,描述系统的功能,通过该图可以迅速的了解系统的功能模块及其关系)、类图(描述类以及类与类之间的关系,通过该图可以快速了解系统)、时序图(描述执行特定任务时对象之间的交互关系以及执行顺序,通过该图可以了解对象能接收的消息也就是说对象能够向外界提供的服务)。

4 面向对象思想

4.1 面向对象的SOLID原则

在这里插入图片描述

1 单一职责原则

一个类只应承担一种责任。换句话说,让一个类只做一件事。如果需要承担更多的工作,那么分解这个类。

2 开放封闭原则

实体应该对扩展是开放的,对修改是封闭的。即,可扩展(extension),不可修改(modification)。

3 里氏替换原则

一个对象在其出现的任何地方,都可以用子类实例做替换,并且不会导致程序的错误。换句话说,当子类可以在任意地方替换基类且软件功能不受影响时,这种继承关系的建模才是合理的。

4 接口分离原则

客户(client)不应被强迫依赖它不使用的方法。即一个类实现的接口中,包含了它不需要的方法。将接口拆分成更小和更具体的接口,有助于解耦,从而更容易重构、更改。

5 依赖倒置原则

  1. 高层次的模块不应依赖低层次的模块,他们都应该依赖于抽象。
  2. 抽象不应依赖于具体实现,具体实现应依赖抽象。

6 扩展:IOC和DI

控制反转(IOC)和依赖注入(DI)是Spring中最重要的核心概念之一,而两者实际上是一体两面的。

  • 依赖注入
    • 一个类依赖另一个类的功能,那么就通过注入,如构造器、setter方法等,将这个类的实例引入。
    • 侧重于实现。
  • 控制反转
    • 创建实例的控制权由一个实例的代码剥离到IOC容器控制,如xml配置中。
    • 侧重于原理。
    • 反转了什么:原先是由类本身去创建另一个类,控制反转后变成了被动等待这个类的注入。

2 类与对象

在这里插入图片描述

  • 类的成员变量:对象状态

  • 类的成员函数:对象行为

  • 类的静态变量、类的静态函数

    • 没有this引用,静态变量全局只有一份

    • 普通函数引用静态变量、函数?可以

    • 对象上引用静态变量、函数?编译警告

    • 静态函数引用普通成员变量、函数:编译错误

计算机网络

1 HTTP协议

1.1 客户端与服务器

  • 通过发送请求获取服务器资源的web浏览器叫做客户端
  • web浏览器通过指定的访问地址获取服务器上的资源
  • HTTP客户端和HTTTP服务器共同构成万维网的基本组件

1.1 URI和URL

  • URI,服务器资源名,统一资源标识符,分为URL和URN
  • URL,统一资源定位符,表示服务器上资源的特定位置
  • URN,统一资源名,是特定内容的唯一名称

2 TCP连接的建立与释放

2.1 三次握手

  • 第一次握手
    • 建立连接,客户端发送连接请求报文段
    • 把标有SYN的数据包发给服务器
  • 第二次握手
    • 服务器收到客户端的SYN报文段
    • 服务器发送标有SYN / ACK的数据包
  • 第三次握手
    • 客户端收到服务器端的SYN / ACK数据包
    • 向服务端发送标有ACK的数据包

2.2 四次挥手

  • 第一次挥手
    • 客户端向服务器发送FIN=1报文段
    • 表示客户端没有数据要发送给服务端
  • 第二次挥手
    • 服务器收到客户端发送的FIN报文段
    • 服务器向客户端发送ACK报文段
  • 第三次挥手
    • 服务器向客户端发送FIN报文段,请求关闭连接
  • 第四次挥手
    • 客户端收到服务器发送的FIN报文段,向服务器发送ACK报文段
    • 服务器收到客户端的ACK报文段,关闭连接
    • 客户端等待2MSL后,关闭连接

3 网络模型分层

3.1 OSI参考模型分层

编号 名称 描述
7 应用层 提供应用程序之间通信
6 表示层 处理数据格式,数据加密等
5 会话层 建立维护和管理会话
4 传输层 建立主机端到端的连接
3 网络层 寻址和路由选择
2 数据链路层 提供介质访问、链路管理
1 物理层 比特流传输

3.2 TCP/IP 分层模型

在这里插入图片描述

4 TCP和UDP

4.1 面向报文(UDP)和面向字节流(TCP)的区别

在这里插入图片描述

4.2 面向报文(UDP)和面向字节流(TCP)的比较

协议 TCP UDP
可靠性 可靠 不可靠
连接性 面向连接 无连接
报文 面向字节流 面向报文(保留报文的边界)
效率 传输效率低 传输效率高
双工性 全双工 一对一,一对多,多对一,多对多
流量控制 滑动窗口
拥塞控制 慢开始,拥塞避免,快重传,快恢复

5 www(万维网)

www是world wide web的简称,也称web、3w等。www是基于客户机/服务器方式的信息发现技术和超文本传输技术的综合。www服务器通过超文本标记语言(HTML)把信息组织成为图文并茂的超文本,利用链接从一个站点跳转到另一个站点。这样一来,彻底摆脱了以前查询工具只能按特定路径一步步地查询信息地限制。

5.1 万维网

  • WWW (World Wide Web,万维网)是存储在Internet计算机中、数量巨大的文档的集合。
  • 这些文档称为页面,它是一种超文本( Hypertext)信息,可以用于描述超媒体。
  • 文本、图形、视频、音频等多媒体,称为超媒体( Hypermedia)。
  • Web上的信息是由彼此关联的文档组成的,而使其连接在一起的是超链接( Hyperlink)

5.2 超文本

  • 超文本(Hypertext)是由一个叫做网页浏览器(Web browser)的程序显示。
  • 网页浏览器从网页服务器取回称为“文档”或“网页”的信息并显示。
  • 通常是显示在计算机显示器。
  • 人可以跟随网页上的超链接(Hyperlink),再取回文件,甚至也可以送出数据给服务器。
  • 顺着超链接走的行为又叫浏览网页。相关的数据通常排成一群网页,又叫网站。

5.3 网上冲浪

  • 网上冲浪(Surfing the Internet,浏览网络)
  • 最早由一个叫简・阿莫尔・泡利(Jean Armour Poly)的作家通过他的作品《网上冲浪》使这个概念被大众接受。
  • 这本书由威尔逊出版社在1992年6月正式出版。泡利在互联网领域被称作“网络妈妈”(Netmom)

5.4 网页、网页文件、网站

  • 网页是网站的基本信息单位,是WWW的基本文档。它由文字、图片、动画、声音等多种媒体信息以及链接组成,是用HTML编写的,通过链接实现与其他网页或网站的关联和跳转
  • 网页文件是用HTML(标准通用标记语言下的一个应用)编写的,可在WWW上传输,能被浏览器识别显示的文本文件。其扩展名是.htm和.html
  • 网站由众多不同内容的网页构成,网页的内容可体现网站的全部功能。通常把进入网站首先看到的网页称为首页或主页(homepage),例如,新浪、网易、搜狐就是国内比较知名的大型门户网站.

5.5 HTTP 协议

HTTP是Hypertext Transfer Protocol 的缩写,即超文本传输协议。 顾名思义,HTTP提供了访问超文本信息的功能,是WWW浏览器和WWW服务器之间的应用层通信协议。HTTP协议是用于分布式协作超文本信息系统的、通用的、面向对象的协议。通过扩展命令,它可用于类似的任务,如域名服务或分布式面向对象系统。WWW使用HTTP协议传输各种超文本页面和数据

HTTP协议会话过程包括4个步骤。
(1)建立连接:客户端的浏览器向服务端发出建立连接的请求,服务端给出响应就可以建立连接了。
(2)发送请求:客户端按照协议的要求通过连接向服务端发送自己的请求。
(3)给出应答:服务端按照客户端的要求给出应答,把结果(HTML文件)返回给客户端。
(4)关闭连接:客户端接到应答后关闭连接.

HTTP协议是基于TCP/IP之上的协议,它不仅保证正确传输超文本文档,还确定传输文档中的哪一部分,以及哪部分内容首先显示(如文本先于图形)等。

5.6 FTP 协议

  • 文件传输协议(FTP)是Internet中用于访问远程机器的一个协议,它使用户可以在本地机和远程机之间进行有关文件的操作。
  • FTP协议允许传输任意文件并且允许文件具有所有权与访问权限。
  • 通过FTP协议,可以与internet上的FTP服务器进行文件的上传或下载等动作。
  • 和其他Internet应用一样,FTP也采用了客户端/服务器模式,它包含客户端FTP和服务器FTP
  • 客户端FTP启动传送过程,而服务器FTP对其做出应答。
  • 在Internet上有一些网站,它们依照FTP协议提供服务,让网友们进行文件的存取
  • 网上的用户要连上FTP服务器,就是用到FTP的客户端软件。
  • 通常Windows都有ftp命令,这实际就是一个命令行的FTP客户端程序,
  • 另外常用的FTP客户端程序还有CuteFTP、Leapftp、FlashFXP等
  • HTTP将用户的数据,包括用户名和密码都明文传送,具有安全隐患,容易被窃听到.
  • 对于具有敏感数据的传送,可以使用具有保密功能的HTTPS(Secure Hypertext Transfer Protocol)协议。

6 图灵奖

  • 图灵奖(Turing Award),全称“A.M. 图灵奖(A.M Turing Award)”,由美国计算机协会(ACM)于1966年设立,专门奖励那些对计算机事业作出重要贡献的个人。
  • 其名称取自计算机科学的先驱、英国科学家艾伦·麦席森·图灵(Alan M. Turing)。
  • 由于图灵奖对获奖条件要求极高,评奖程序又是极严,一般每年只奖励一名计算机科学家,只有极少数年度有两名合作者或在同一方向作出贡献的科学家共享此奖。
  • 因此它是计算机界最负盛名、最崇高的一个奖项,有“计算机界的诺贝尔奖”之称。
  • 每一年的图灵奖一般在下一年的3月下旬颁发,从1966年至2019年的图灵奖共授予了72名获奖者。
  • 按国籍分,美国学者最多,欧洲学者偶见之,华人学者目前仅有2000年图灵奖得主姚期智(现在清华大学、香港中文大学)。
  • 据相关资料统计,截止至2020年3月,世界各高校的校友、教授以及研究人员中,美国斯坦福大学的图灵奖人数位列世界第一(28位)、美国麻省理工学院(26位)位列世界第二、美国加州大学伯克利分校(25位)位列世界第三,美国哈佛大学(14位)、美国普林斯顿大学(14位)并列世界第四

数据库

1 数据库设计的范式

1.1 概念

  • 设计数据库时,需要遵循的规范,越高的范式,数据库冗余度越小
  • 要遵循后边的范式要求,必须遵循前边的范式要求

1.2 第一范式

  • 每一列都是不可分割的原子数据项

1.3第二范式

  • 在1NF的基础上,非码属性必须完全依赖于候选码

  • 在1NF的基础上,消除了非主属性对主码的部分函数依赖

  • 函数依赖:A–>B

    • 如果通过A属性(属性组)的值,可以确定唯一B属性的值,则称B依赖于A
    • 例如:学号–>姓名;(学号,课程名称)–> 分数
  • 完全函数依赖:A->B

    • 如果A是一个属性组,则B属性值的确定需要依赖于属性组中所有的属性值
    • 例如:(学号,课程名称)–> 分数
  • 部分函数依赖:A->B

    • 如果A是一个属性组 ,则B属性值的确定只需要依赖于A属性组中某一些值即可
    • 例如:(学号,课程名称)-> 姓名
  • 传递函数依赖:A–>B,B->C

    • 如果通过A属性(属性组)的值,可以确定唯一B属性值,再通过B属性(属性组)的值可以唯一确定C属性的值,则称C传递A
    • 例如:学号 --> 系名,系名 –> 系主任
  • 码:

    • 如果在一张表中,一个属性或属性组,被其他所有属性所完全依赖,则称这个属性或属性组为该表的码
    • 例如:(学号,课程名称)

1.4 第三范式

  • 在2NF基础上,任何非主属性不依赖于其他非主属性
  • 在2NF基础上,消除了传递依赖

2 事务的四大特征

  • 原子性:事务是不可分割的最小操作单位,要么同时成功,要么同时失败
  • 持久性:当事务提交或回滚后,数据库会持久化的保存数据
  • 隔离性:多个事务之间相互独立
  • 一致性:事务操作前后数据总量不变

常见代码题

1.链表

容易理解,代码难写

public class Node {
    private final int value;
    private Node next;

    public int getValue() {
        return value;
    }

    public Node getNext() {
        return next;
    }

    public void setNext(Node next) {
        this.next = next;
    }

    Node(int value) {
        this.value = value;
        this.next = null;
    }

    public static void printList(Node head) {
        while (head != null) {
            System.out.print(head.getValue() + " ");
            head = head.next;
        }
        System.out.println();
    }
}

1.1 创建链表

  • 递归方式
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class LinkedListCreator {
    /**
     * Create a linked list.
     *
     * @param values The data to create a list.
     * @return Head of the linked list
     * The returned linked list ends with last node with getNext() == null.
     */
    public Node createLinkedList(List<Integer> values) {
        if (values.isEmpty()) {
            return null;
        }
        Node firstNode = new Node(values.get(0));
        Node headOfSublist = createLinkedList(values.subList(1, values.size()));
        firstNode.setNext(headOfSublist);
        return firstNode;
    }
}
  • 非递归方式
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class LinkedListCreator {
    /**
     * Create a linked list.
     *
     * @param values The data to create a list.
     * @return Head of the linked list
     * The returned linked list ends with last node with getNext() == null.
     */
    public Node createLinkedList(List<Integer> values) {
        Node prev = null;
        Node head = null;
        for (Integer value : values) {
            Node node = new Node(value);
            if (prev != null) {
                prev.setNext(node);
            } else {
                head = node;
            }
            prev = node;
        }
        return head;
    }

    public Node createLargeLinkedList(int size) {
        Node prev = null;
        Node head = null;
        for (int i = 0; i < size; i++) {
            Node node = new Node(i);
            if (prev != null) {
                prev.setNext(node);
            } else {
                head = node;
            }
            prev = node;
        }
        return head;
    }
}

1.2 反转列表

  • 递归方式
import java.util.ArrayList;
import java.util.Arrays;

public class LinkedListReverser {
    public Node reverseLinkedList(Node head) {
        if (head == null || head.getNext() == null) {
            return head;
        }
        Node newHead = reverseLinkedList(head.getNext());
        head.getNext().setNext(head);
        head.setNext(null);
        return newHead;
    }
}
  • 非递归方式
import edu.sust.list.LinkedListCreator;
import edu.sust.list.Node;

import java.util.ArrayList;
import java.util.Arrays;

public class LinkedListReverser {
    public Node reverseLinkedList(Node head) {
        Node newHead = null;
        Node curHead = head;
        //Loop invariant.
        //newHead points to the linked list already reversed.
        //curHead points to the linked list not yet reversed.
        while (curHead != null) {
            Node next = curHead.getNext();
            curHead.setNext(newHead);
            newHead = curHead;
            curHead = next;
        }
        return newHead;
    }
}

1.3删除指定值

public class LinkedListDeleter {
    public Node deleteIfEquals(Node head, int value) {

        if (head != null && head.getValue() == value) {
            head = head.getNext();
        }
        if (head == null) {
            return null;
        }
        Node prev = head;
        /*
        loop invariant:
        list nodes from head up to prev has been processed.
        Nodes with values equal to value are deleted.
         */
        while (prev.getNext() != null) {
            if (prev.getNext().getValue() == value) {
                //delete it
                prev.setNext(prev.getNext().getNext());
            }
        }
        return head;
    }
}

2.二分查找

import javax.xml.bind.SchemaOutputResolver;

public class BinarySearch {
    /**
     * Searches element k in a sorted array
     *
     * @param arr a sorted array
     * @param k   the element to search
     * @return index in arr where k is. -1 if not found.
     */
    public static int binarySearch(int[] arr, int k) {
        int a = 0;
        int b = arr.length;
        //Loop invariant:[a,b) is a valid range.(a<=b)
        //k may only be within range [a,b)
        while (a < b) {
            int m = a + (b - a) / 2;
            if (k < arr[m]) {
                b = m;
            } else if (k > arr[m]) {
                a = m + 1;
            } else {
                return m;
            }
        }
        return -1;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_40507857/article/details/106068420
今日推荐