算法面试指南

做者:Educative

翻译:疯狂的技术宅前端

https://www.educative.io/blog...ios

未经容许严禁转载c++

image.png

算法是技术面试的重要组成部分,尤为是在国内外的大厂中。本文将为你介绍在面试中须要了解的常见算法以及提升它们效率的方法(这是面试中常见的问题),最后会为你提供一些练习题。程序员

基本概述

你须要审视的基本概念是:面试

  • 条件语句:if-else 语句,switch 语句和条件表达式
  • 循环:for 循环,while 循环,do-while 循环
  • 函数:迭代函数和递归函数
  • 数组

一旦掌握了基础知识,就能够开始进入在面试以前应该了解的中间概念;具体来讲,本文将向你展现一些关键的算法范例(以及使它们高效的方法),这些范例对于学习解决面试中的编码问题相当重要。算法

渐进分析-提升程序效率

在咱们深刻研究算法范式以前,应该对计算机程序相对于算法的时间复杂性和效率说些什么——一种被称为“渐近分析”的概念。在面试中,可能不会要求你直接计算算法的复杂度,但可能会要求你计算所编写的算法的复杂度或让你改善一个算法的复杂度。segmentfault

复杂度是算法效率的近似度量,而且与你编写的每一个算法都相有关。这是全部程序员都必须意识到的事情。有两种复杂度:时间和空间。时间复杂度和空间复杂度实质上是算法处理某些输入时将分别花费多少时间和多少空间的近似值。一般要解决如下三个问题:数组

  • 最佳状况——表示为 Big Omega 或 Ω(n)
  • 平均状况——表示为 Big Theta 或Θ(n)
  • 最坏的状况——表示为 Big O 表示法或 O(n)

Big O 是分析算法的首选方法,由于在大多数状况下,平均状况和最佳案例没法洞察算法的效率。服务器

找到算法的 Big O 复杂度

若是你在面试中被要求找到算法的 Big O 复杂性,这是通常的经验法则:微信

  • 删除前导常数项
  • 忽略低阶项

例:找到时间复杂度为 3n³ + 4n + 2的算法的 Big O 复杂度,将其简化为O(n³)。

渐近分析——怎样在不给你方程的状况下计算时间复杂度

计算算法的时间复杂度时,你须要采起三个步骤:

  • 列出代码中的全部基本操做
  • 计算每次执行的次数
  • 将全部计数加起来获得一个方程

这是一个简单的例子,用于测量大小为 n 的 for 循环的时间复杂度。这是一个大小为 n 的循环:

#include <iostream>
using namespace std;
int main(){
  int n = 10;  //  0(1)
  int sum = 0; // 0(1)
  for (int i=0; i<n; i++)
    sum+=2; // 0(1)
  cout << sum; // 0(1)
  return 0;
}

首先,将代码分红多个单独的操做,而后计算执行该代码的次数,以下所示:

image.png

在对每一个操做执行了多少次进行计数以后,只需将全部这些计数相加便可得出该程序的时间复杂度。

$$ \begin{align} 时间复杂度 & = 1 + 1 + 1 +(n + 1)+ n + n + 1 \\ & = 3 +(n + 1)+ 2n + 1 \\ & => 3n + 5 \end{align} $$

渐进分析的通常技巧:

  • 列表或数组每次通过 $c \times 长度$ 的次数进行迭代时,最有可能的时间复杂度是 O(n) 。
  • 当你看到一个问题,每次问题空间中的元素数量减半时,它的时间复杂度极可能是 O(logn)。
  • 只要有一个单独的嵌套循环,问题的复杂度就极可能是二次方。

用于计算算法时间复杂度的有用公式:

image.png

什么是算法范式?

算法范式是“构建有效解决问题的通用方法”;换句话说,它们是解决问题的方法、策略或技术,对于每一个程序员都是必不可少的。花时间学习这些,由于你颇有可能会在面试中用到其中一种或多种算法。

算法范式之因此出色,是由于它们奠基了适合解决各类不一样问题的框架,包括:

  • 分治——一种将问题分解为较小子问题的模式,而后将其递归求解并组合起来(对于树排序来讲很是有用)。
  • 回溯 ——一种解决问题的算法技术,它尝试一次逐步构建一个解决方案,并删除那些不能知足问题约束的解决方案。
  • 动态规划——递归函数的优化算法。使用动态规划,你能够保存子问题的结果,这样咱们就能够没必要在稍后须要时从新计算它们。

面试时应注意哪些算法?

  • 暴力法——这种方法要求咱们经过尝试全部可能的方法,来找到问题的解决方案。这一般是最早想到的算法,尽管它可能效率最低,但至少能够保证你可以找到一种解决方案。
  • 贪心算法——一种算法范式,它逐步构建一个解决方案,这意味着它将会选择下一个可以提供最明显且最直接的好处的解决方案。
  • 动态规划(如上所述)
  • 分而治之(如上所述)
  • 排序和搜索算法——归并排序、快速排序、选择排序、冒泡排序、插入排序
  • 图算法——广度优先图遍历,深度优先图遍历

如何进行技术面试

  • 确保你已掌握基础知识。
  • 了解如何使用渐近分析优化程序。
  • 请注意你可使用的不一样算法及其对复杂度的影响。

一组帮你为面试作好准备的练习题

渐近分析:计算下面给出的代码段的 Big O 复杂度。

int main(){
   int n = 10;
   int sum = 0;
   float pie = 3.14;
   
   for (int i=1; i<n; i+=3){
     cout << pie << endl;
     for (int j=1; j<n; J+=2){
       sum += 1;
       cout << sum << endl;
     }
   }
}

排序和搜索算法:实现一个函数,该函数接受两个可变长度的排序数组,并找到两个数组的中位数。

图算法:实现一个函数,该函数返回给定级别的无向图的节点数。

贪心算法:假设存在无限数量的 25 美分,10 美分,5 美分和 1 美分硬币,实现一个函数来计算表明 V 美分的硬币数量。

动态规划算法:一个孩子正在上 n 级楼梯,每次能够走 1 步,2 步或 3 步。实现一个函数,计算孩子上楼梯的可能方式。

分治法:给定 2 个有 k 行和 44 个排序列的二维数组,以及一个大小为 $k \times n$ 的空一维输出数组,用分治法将全部元素从 k 个排序数组复制到 $k \times n$ 个输出数组。

总结

若是你要进行技术面试,必须为展现本身对各类算法的了解作好准备,并了解每种算法的复杂度。熟悉上面提到的算法范例(即分治、暴力、贪婪),谚语云:“实践出真知”,因此你须要花时间去练习实现不一样的算法,并计算其复杂度,由于开发人员在编码时必须意识到这一点。

你能够采起一些步骤来确保下次面试成功:

熟悉各类算法:不要只记住解决方案。花时间了解构成每种算法的模式以及应该采起的方法。

作功课:练习的次数越多,感受就会越温馨。

下一步…学习,准备和练习:只是凭借看老的面试题和博客文章来准备面试是不够的,你须要真正的实践经验。


本文首发微信公众号:前端先锋

欢迎扫描二维码关注公众号,天天都给你推送新鲜的前端技术文章

欢迎扫描二维码关注公众号,天天都给你推送新鲜的前端技术文章

欢迎继续阅读本专栏其它高赞文章:


相关文章
相关标签/搜索