Interviews

软件工程技术面试个人指南。

Maintainer - Kevin Naughton Jr.

其他语言版本

目录

在线练习

在线面试编程

数据结构

Linked List

  • 链表即是由节点(Node)组成的线性集合,每个节点可以利用指针指向其他节点。它是一种包含了多个节点的、能够用于表示序列的数据结构。
  • 单向链表: 链表中的节点仅指向下一个节点,并且最后一个节点指向空。
  • 双向链表: 其中每个节点具有两个指针 p、n,使得 p 指向先前节点并且 n 指向下一个节点;最后一个节点的 n 指针指向 null。
  • 循环链表:每个节点指向下一个节点并且最后一个节点指向第一个节点的链表。
  • 时间复杂度:
    • 索引: O(n)
    • 搜索: O(n)
    • 插入: O(1)
    • 移除: O(1)

Stack

  • 栈是元素的集合,其包含了两个基本操作:push 操作可以用于将元素压入栈,pop 操作可以将栈顶元素移除。
  • 遵循后入先出(LIFO)原则。
  • 时间复杂度:
  • 索引: O(n)
  • 搜索: O(n)
  • 插入: O(1)
  • 移除: O(1)

Queue

  • 队列是元素的集合,其包含了两个基本操作:enqueue 操作可以用于将元素插入到队列中,而 dequeue 操作则是将元素从队列中移除。
  • 遵循先入先出原则 (FIFO)。
  • 时间复杂度:
  • 索引: O(n)
  • 搜索: O(n)
  • 插入: O(1)
  • 移除: O(1)

Tree

  • 树是无向、连通的无环图。

Binary Tree

  • 二叉树即是每个节点最多包含左子节点与右子节点这两个节点的树形数据结构。
  • 满二叉树: 树中的每个节点仅包含 0 或 2 个节点。
  • 完美二叉树(Perfect Binary Tree): 二叉树中的每个叶节点都拥有两个子节点,并且具有相同的高度。
  • 完全二叉树: 除最后一层外,每一层上的结点数均达到最大值;在最后一层上只缺少右边的若干结点。

Binary Search Tree

  • 二叉搜索树(BST)是一种特殊的二叉树,其任何节点中的值都会大于或者等于其左子树中存储的值并且小于或者等于其右子树中存储的值。
  • 时间复杂度:
    • 索引: O(log(n))
    • 搜索: O(log(n))
    • 插入: O(log(n))
    • 删除: O(log(n))

Trie

  • 字典树,又称基数树或者前缀树,能够用于存储键为字符串的动态集合或者关联数组的搜索树。树中的节点并没有直接存储关联键值,而是该节点在树中的挂载位置决定了其关联键值。某个节点的所有子节点都拥有相同的前缀,整棵树的根节点则是空字符串。

Fenwick Tree

  • 树状数组又称 Binary Indexed Tree,其表现形式为树,不过本质上是以数组实现。数组中的下标代表着树中的顶点,每个顶点的父节点或者子节点的下标能够通过位运算获得。数组中的每个元素包含了预计算的区间值之和,在整棵树更新的过程中同样会更新这些预计算的值。
  • 时间复杂度:
    • 区间求值: O(log(n))
    • 更新: O(log(n))

Segment Tree

  • 线段树是用于存放间隔或者线段的树形数据结构,它允许快速的查找某一个节点在若干条线段中出现的次数.
  • 时间复杂度:
    • 区间查询: O(log(n))
    • 更新: O(log(n))

Heap

  • 堆是一种特殊的基于树的满足某些特性的数据结构,整个堆中的所有父子节点的键值都会满足相同的排序条件。堆更准确地可以分为最大堆与最小堆,在最大堆中,父节点的键值永远大于或者等于子节点的值,并且整个堆中的最大值存储于根节点;而最小堆中,父节点的键值永远小于或者等于其子节点的键值,并且整个堆中的最小值存储于根节点。
  • 时间复杂度:
    • 访问最大值 / 最小值: O(1)
    • 插入: O(log(n))
    • 移除最大值 / 最小值: O(log(n))

Hashing

  • 哈希能够将任意长度的数据映射到固定长度的数据。哈希函数返回的即是哈希值,如果两个不同的键得到相同的哈希值,即将这种现象称为碰撞。
  • Hash Map: Hash Map 是一种能够建立起键与值之间关系的数据结构,Hash Map 能够使用哈希函数将键转化为桶或者槽中的下标,从而优化对于目标值的搜索速度。
  • 碰撞解决
    • 链地址法(Separate Chaining): 链地址法中,每个桶是相互独立的,包含了一系列索引的列表。搜索操作的时间复杂度即是搜索桶的时间(固定时间)与遍历列表的时间之和。
    • 开地址法(Open Addressing): 在开地址法中,当插入新值时,会判断该值对应的哈希桶是否存在,如果存在则根据某种算法依次选择下一个可能的位置,直到找到一个尚未被占用的地址。所谓开地址法也是指某个元素的位置并不永远由其哈希值决定。

Graph

  • 图是一种数据元素间为多对多关系的数据结构,加上一组基本操作构成的抽象数据类型。

    • 无向图(Undirected Graph): 无向图具有对称的邻接矩阵,因此如果存在某条从节点 u 到节点 v 的边,反之从 v 到 u 的边也存在。
    • 有向图(Directed Graph): 有向图的邻接矩阵是非对称的,即如果存在从 u 到 v 的边并不意味着一定存在从 v 到 u 的边。

算法

排序

快速排序

  • 稳定: 否
  • 时间复杂度:
    • 最优时间: O(nlog(n))
    • 最坏时间: O(n^2)
    • 平均时间: O(nlog(n))

归并排序

  • 归并排序是典型的分治算法,它不断地将某个数组分为两个部分,分别对左子数组与右子数组进行排序,然后将两个数组合并为新的有序数组。
  • 稳定: 是
  • 时间复杂度:
    • 最优时间: O(nlog(n))
    • 最坏时间: O(nlog(n))
    • 平均时间: O(nlog(n))

桶排序

  • 桶排序将数组分到有限数量的桶子里。每个桶子再个别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排序)。
  • 时间复杂度:
    • 最优时间: Ω(n + k)
    • 最坏时间: O(n^2)
    • 平均时间:Θ(n + k)

基数排序

  • 基数排序类似于桶排序,将数组分割到有限数目的桶中;不过其在分割之后并没有让每个桶单独地进行排序,而是直接进行了合并操作。
  • 时间复杂度:
    • 最优时间: Ω(nk)
    • 最坏时间: O(nk)
    • 平均时间: Θ(nk)

图算法

深度优先搜索

  • 深度优先算法是一种优先遍历子节点而不是回溯的算法。
  • 时间复杂度: O(|V| + |E|)

广度优先搜索

  • 广度优先搜索是优先遍历邻居节点而不是子节点的图遍历算法。
  • 时间复杂度: O(|V| + |E|)

拓扑排序

  • 拓扑排序是对于有向图节点的线性排序,如果存在某条从 u 到 v 的边,则认为 u 的下标先于 v。
  • 时间复杂度: O(|V| + |E|)

Dijkstra 算法

  • Dijkstra 算法 用于计算有向图中单源最短路径问题。
  • 时间复杂度: O(|V|^2)

Bellman-Ford 算法

  • Bellman-Ford 算法是在带权图中计算从单一源点出发到其他节点的最短路径的算法。
  • 尽管算法复杂度大于 Dijkstra 算法,但是它适用于包含了负值边的图。
  • 时间复杂度:
    • 最优时间: O(|E|)
    • 最坏时间: O(|V||E|)

Floyd-Warshall 算法

  • Floyd-Warshall 算法 能够用于在无环带权图中寻找任意节点的最短路径。
  • 时间复杂度:
    • 最优时间: O(|V|^3)
    • 最坏时间: O(|V|^3)
    • 平均时间: O(|V|^3)

Prim 算法

  • Prim 算法是用于在带权无向图中计算最小生成树的贪婪算法。换言之,Prim 算法能够在图中抽取出连接所有节点的边的最小代价子集。
  • 时间复杂度: O(|V|^2)

Kruskal 算法

  • Kruskal 算法同样是计算图的最小生成树的算法,与 Prim 的区别在于并不需要图是连通的。
  • 时间复杂度: O(|E|log|V|)

位运算

  • 位运算即是在位级别进行操作的技术,合适的位运算能够帮助我们得到更快地运算速度与更小的内存使用。
  • 测试第 k 位: s & (1 << k)
  • 设置第 k 位: s |= (1 << k)
  • 第 k 位置零: s &= ~(1 << k)
  • 切换第 k 位值: s ^= ~(1 << k)
  • 乘以 2: s << n
  • 除以 2: s >> n
  • 交集: s & t
  • 并集: s | t
  • 减法: s & ~t
  • 交换 x = x ^ y ^ (y = x)
  • 取出最小非 0 位(Extract lowest set bit): s & (-s)
  • 取出最小 0 位(Extract lowest unset bit): ~s & (s + 1)
  • 交换值: x ^= y; y ^= x; x ^= y;

算法复杂度分析

大 O 表示

  • 大 O 表示 用于表示某个算法的上限,往往用于描述最坏的情况。

小 O 表示

  • 小 O 表示用于描述某个算法的渐进上界,不过二者要更为紧密。

大 Ω 表示

  • 大 Ω 表示用于描述某个算法的渐进下界。

小 ω 表示

  • Little Omega Notation用于描述某个特定算法的下界,不过不一定很靠近。

Theta Θ 表示

  • Theta Notation用于描述某个确定算法的确界。

视频教程

面试书籍

  • Competitive Programming 3 - Steven Halim & Felix Halim
  • Cracking The Coding Interview - Gayle Laakmann McDowell
  • Cracking The PM Interview - Gayle Laakmann McDowell & Jackie Bavaro

计算机科学与技术资讯

java算法数据结构的更多相关文章

  1. java项目——数据结构实验报告

    java项目——数据结构总结报告 20135315  宋宸宁 实验要求 1.用java语言实现数据结构中的线性表.哈希表.树.图.队列.堆栈.排序查找算法的类. 2.设计集合框架,使用泛型实现各类. ...

  2. Java 算法(一)贪心算法

    Java 算法(一)贪心算法 数据结构与算法目录(https://www.cnblogs.com/binarylei/p/10115867.html) 一.贪心算法 什么是贪心算法?是指在对问题进行求 ...

  3. 【转】Java学习---Java核心数据结构(List,Map,Set)使用技巧与优化

    [原文]https://www.toutiao.com/i6594587397101453827/ Java核心数据结构(List,Map,Set)使用技巧与优化 JDK提供了一组主要的数据结构实现, ...

  4. Java同步数据结构之ConcurrentSkipListMap/ConcurrentSkipListSet

    引言 上一篇Java同步数据结构之Map概述及ConcurrentSkipListMap原理已经将ConcurrentSkipListMap的原理大致搞清楚了,它是一种有序的能够实现高效插入,删除,更 ...

  5. java算法--普通队列

    数据结构队列 首先明确一下队列的概念. 队列是一种有序列表,使用数组的结构来存储队列的数据. 队列是一种先进先出的算法.由前端加入,由后端输出. 如下图: ​ 第一个图 第二个图 第三个图 这就是队列 ...

  6. java算法--稀疏数组

    数据结构必要知识 线性结构 线性结构是最常用的数据结构,数据元素之间存在一对一的线性关系. 线性结构有两种不同的存储结构,即顺序存储结构和链式存储结构.顺序存储的线性表称为顺序表,顺序表中的存储元素是 ...

  7. JAVA常用数据结构及原理分析

    JAVA常用数据结构及原理分析 http://www.2cto.com/kf/201506/412305.html 前不久面试官让我说一下怎么理解java数据结构框架,之前也看过部分源码,balaba ...

  8. JAVA算法系列 冒泡排序

    java算法系列之排序 手写冒泡 冒泡算是最基础的一个排序算法,简单的可以理解为,每一趟都拿i与i+1进行比较,两个for循环,时间复杂度为 O(n^2),同时本例与选择排序进行了比较,选择排序又叫直 ...

  9. JAVA算法系列 快速排序

    java算法系列之排序 手写快排 首先说一下什么是快排,比冒泡效率要高,快排的基本思路是首先找到一个基准元素,比如数组中最左边的那个位置,作为基准元素key,之后在最左边和最右边设立两个哨兵,i 和 ...

随机推荐

  1. linux服务器卸载本机默认安装的jdk

    1.      查看系统安装的版本情况: rpm -qa | grep jdk rpm -qa | grep gcj 2.      查看并删除 [root@iZ2zeedm3x12d8xb4g15a ...

  2. 高并发之web服务器负载均衡简单介绍

    负载均衡种类 F5,七层负载均衡,四层负载均衡 Nginx负载均衡 内置策略.扩展策略 内置策略:IPHash.加权轮询 扩展策略:fair策略.通用hash.一致性hash 加权轮询策略 首先将请求 ...

  3. SpringBoot(九) ElasticSearch 全文检索

    ElasticSearch ​ ElasticSearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口.Elasticsearch是用 ...

  4. Hibernate框架学习(五)——批量查询(概述)

    一.HQL查询(Hibernate Query Language)多表查询,但不复杂时使用 Hibernate独家查询语言,属于面向对象的查询语言 1.基本查询 2.条件查询 注意:HQL语句中不可能 ...

  5. zabbix监控自身为监控机(server)

    Zabbix 监控主机 添加自身为被监控机 这里我的环境已经部署完毕(没有经验的小伙伴可以看我上一篇文章) 等待一会刷新如下页面 字体出现以下亮度就成功了

  6. BZOJ2194: 快速傅立叶之二 FFT_卷积

    Code: #include <cstdio> #include <algorithm> #include <cmath> #include <cstring ...

  7. node——try-catch与异步操作

    //try-catch,用于捕获异常 //try-catch在node中只能捕获同步的异常,不能捕获异步异常 var fs=require('fs'); /*fs.writeFile('./abc.t ...

  8. luogu p1003

    P1003 题意 经过多个矩形(1e3)覆盖后后某个坐标属于那个矩形(仅仅是一次询问) 大水题,直接的做法,从后向前处理矩形是否覆盖查询的点,若覆盖,则是该矩形编号 题解 int get_num(){ ...

  9. My97 DatePicker获取自定义日期的前一天

    1.控件,获取第一个input中的时间,再将这个时间的前一天赋值给第二个input <input type="text" class="form-control i ...

  10. 关于Number的属性和方法你知晓几分?速来围观!

    1.Number.isFinite() 方法用来检测传入的参数是否是一个有穷数(finite number)返回值为布尔值. 和全局的 isFinite() 函数相比,这个方法不会强制将一个非数值的参 ...