在互联网面试的过程中,有一个环节是逃不掉的,就是算法面试。一般,面试官出的面试题都是从题库里抽出来的,很少有自己出新题的(当然,算法笔试过程除外)。所以,只要我们刷题刷的足够多,就总有概率遇到原题。当然,我们也可以押题,毕竟,一些高频率的题目总是有代表性的。
本文列举了20个在计算机面试过程中经常被问到的算法题,排名不分前后,这些题目也只是代表我自己在面试过程中的体会,所以有些好题目没有加入进来也请轻喷,仅供参考。
给定一个非空的整数数组,返回其中出现频率前 k 高的元素。
示例 1:
输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
示例 2:
输入: nums = [1], k = 1
输出: [1]
解题思路:
使用快排的思想,对数组进行快速排序,取前k 个元素,也可以使用堆排序。
在此处获取完整题目和答案:https://leetcode-cn.com/problems/top-k-frequent-elements/
类似的还有:
根据一棵树的前序遍历与中序遍历构造二叉树。
**注意:**你可以假设树中没有重复的元素。
例如,给出
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:
3
/ \
9 20
/ \
15 7
解题思路:
利用前序和中序遍历的特点,递归的构建二叉树
在此处获取完整题目和答案:https://leetcode-cn.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/
类似的还有:
反转一个单链表。
示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
解题思路:
需要注意的是链表的界限,即开头和结尾需要特别注意不要越界
在此处获取完整题目和答案:https://leetcode-cn.com/problems/reverse-linked-list/
类似的还有:
给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。
最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。
你可以假设除了整数 0 之外,这个整数不会以零开头。
示例 :
输入:digits = [1,2,3]
输出:[1,2,4]
解释:输入数组表示数字 123。
解题思路:
注意进位问题,设置一个标志位mark,表示是否进位。另外,在最后需要注意 9 这个数字。
在此处获取完整题目和答案:https://leetcode-cn.com/problems/plus-one/
类似的还有:
运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制 。
实现 LRUCache
类:
LRUCache(int capacity)
以正整数作为容量 capacity
初始化 LRU 缓存int get(int key)
如果关键字 key
存在于缓存中,则返回关键字的值,否则返回 -1
。void put(int key, int value)
如果关键字已经存在,则变更其数据值;如果关键字不存在,则插入该组「关键字-值」。当缓存容量达到上限时,它应该在写入新数据之前删除最久未使用的数据值,从而为新的数据值留出空间。解题思路:
其实考察的就是看你是否掌握了LRU缓存算法,需要掌握了双向链表和哈希表的用法就不难
在此处获取完整题目和答案:https://leetcode-cn.com/problems/lru-cache/
类似的还有:
给定一个 没有重复 数字的序列,返回其所有可能的全排列。
示例:
输入: [1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
解题思路:
回溯法,注意结束条件是什么
在此处获取完整题目和答案:https://leetcode-cn.com/problems/permutations/
类似的还有:
给定一个链表,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next
指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 pos
来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos
是 -1
,则在该链表中没有环。注意:pos
不作为参数进行传递,仅仅是为了标识链表的实际情况。
如果链表中存在环,则返回 true
。 否则,返回 false
。
示例:
输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。
解题思路:
双指针法,需要注意的是,有时候会考察为什么“双指针法”有效,数学原理是什么?提前走一步可以,相差两步、三步呢?
在此处获取完整题目和答案:https://leetcode-cn.com/problems/linked-list-cycle/
类似的还有:
你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。
示例 1:
输入:[1,2,3,1]
输出:4
解释:偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。
偷窃到的最高金额 = 1 + 3 = 4 。
在此处获取完整题目和答案:https://leetcode-cn.com/problems/house-robber/
类似的还有:
给定一个整数数组 nums
和一个整数目标值 target
,请你在该数组中找出 和为目标值 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
你可以按任意顺序返回答案。
示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
解题思路:
先排序,之后使用双指针法,从开头和结尾两处开始遍历
在此处获取完整题目和答案:https://leetcode-cn.com/problems/two-sum/
类似的还有:
给定一个包含了一些 0
和 1
的非空二维数组 grid
。
一个 岛屿 是由一些相邻的 1
(代表土地) 构成的组合,这里的「相邻」要求两个 1
必须在水平或者竖直方向上相邻。你可以假设 grid
的四个边缘都被 0
(代表水)包围着。
找到给定的二维数组中最大的岛屿面积。(如果没有岛屿,则返回面积为 0
。)
示例 1:
[[0,0,1,0,0,0,0,1,0,0,0,0,0],
[0,0,0,0,0,0,0,1,1,1,0,0,0],
[0,1,1,0,1,0,0,0,0,0,0,0,0],
[0,1,0,0,1,1,0,0,1,0,1,0,0],
[0,1,0,0,1,1,0,0,1,1,1,0,0],
[0,0,0,0,0,0,0,0,0,0,1,0,0],
[0,0,0,0,0,0,0,1,1,1,0,0,0],
[0,0,0,0,0,0,0,1,1,0,0,0,0]]
对于上面这个给定矩阵应返回 6
。注意答案不应该是 11
,因为岛屿只能包含水平或垂直的四个方向的 1
。
解题思路:
使用广度(深度)优先遍历,得到相连的最大的岛屿面积。注意最好使用标记矩阵,来标记以前遍历过的值
在此处获取完整题目和答案:https://leetcode-cn.com/problems/max-area-of-island/
类似的还有:
给你一个整数数组 nums
,找到其中最长严格递增子序列的长度。
子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7]
是数组 [0,3,1,6,2,2,7]
的子序列。
示例 1:
输入:nums = [10,9,2,5,3,7,101,18]
输出:4
解释:最长递增子序列是 [2,3,7,101],因此长度为 4 。
在此处获取完整题目和答案:https://leetcode-cn.com/problems/longest-increasing-subsequence/
类似的还有:
输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的。
示例1:
输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4
解题思路:
链表的基本操作,注意设置一个开头的空节点,防止边界问题
在此处获取完整题目和答案:https://leetcode-cn.com/problems/merge-two-sorted-lists/
类似的还有:
给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。
示例:
二叉树:[3,9,20,null,null,15,7]
,
3
/ \
9 20
/ \
15 7
返回其层序遍历结果:
[
[3],
[9,20],
[15,7]
]
解题思路:
使用广度优先遍历
在此处获取完整题目和答案:https://leetcode-cn.com/problems/binary-tree-level-order-traversal/
类似的还有:
设计一个支持 push
,pop
,top
操作,并能在常数时间内检索到最小元素的栈。
push(x)
—— 将元素 x 推入栈中。pop()
—— 删除栈顶的元素。top()
—— 获取栈顶元素。getMin()
—— 检索栈中的最小元素。解题思路:
使用两个栈,一个主栈,一个辅助栈
在此处获取完整题目和答案:https://leetcode-cn.com/problems/min-stack/
类似的还有:
有时候,面试官也会考察你所写算法的复杂度
比如,分析一下为什么快速排序的时间复杂度是 n l o g ( n ) nlog(n) nlog(n)
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。
示例 :
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,3,6,9,8,7,4,5]
在此处获取完整题目和答案:https://leetcode-cn.com/problems/spiral-matrix/
实现 pow(x, n) ,即计算 x 的 n 次幂函数(即, x n x^n xn)
示例 :
输入:x = 2.00000, n = 10
输出:1024.00000
解题思路:
实现好实现,就是需要注意的细节很多,考虑n值是负数、x是0值等等特殊的情况
在此处获取完整题目和答案:https://leetcode-cn.com/problems/powx-n/
类似的还有:
把n个骰子扔在地上,所有骰子朝上一面的点数之和为s。输入n,打印出s的所有可能的值出现的概率。
你需要用一个浮点数数组返回答案,其中第 i 个元素代表这 n 个骰子所能掷出的点数集合中第 i 小的那个的概率。
示例 2:
输入: 2
输出: [0.02778,0.05556,0.08333,0.11111,0.13889,0.16667,0.13889,0.11111,0.08333,0.05556,0.02778]
解题思路:
找规律,或者动态规划
在此处获取完整题目和答案:https://leetcode-cn.com/problems/nge-tou-zi-de-dian-shu-lcof/
给定一个包含 n + 1
个整数的数组 nums
,其数字都在 1
到 n
之间(包括 1
和 n
),可知至少存在一个重复的整数。
假设 nums
只有 一个重复的整数 ,找出 这个重复的数 。
示例:
输入:nums = [1,3,4,2,2]
输出:2
解题思路:
二分查找,或者快慢指针
在此处获取完整题目和答案:https://leetcode-cn.com/problems/find-the-duplicate-number/
类似的还有:
给定一个数组 prices
,它的第 i
个元素 prices[i]
表示一支给定股票第 i
天的价格。
你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。
返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0
。
示例:
输入:[7,1,5,3,6,4]
输出:5
解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。
在此处获取完整题目和答案:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/
类似的还有:
最后,附上极客时间里王争的《数据结构与算法之美》学习指导手册中的算法学习路线,他非常好的总结、归纳了学习算法的路线和知识点。
最后,附上极客时间里王争的《数据结构与算法之美》学习指导手册中的算法学习路线,他非常好的总结、归纳了学习算法的路线和知识点。