前言
提起数据结构与算法,大家可能第一时间想到的就是蓝桥杯这种算法竞赛,并不会太过于在意它在面试中的占比。因为在若干年前,你去面试这种互联网公司或者大的IT公司,面试官并不会过于考察你的算法能力,甚至说你会简单的写一些框架,搭一些数据库,就能找到一份不错的工作
但是直至今日,大家会发现面试的门槛越来越高,甚至来说去到一些大公司去面试算法与数据结构的题目已经成为必问了,算法的在面试的占比已经越来越高,在此我整理了一下近几年面试中问的比较频繁的算法题,大家感兴趣的可以看看,看自己能答出来多少。
寻找数组的中心索引
数组中某一个下标,左右两边的元素之后相等,该下标即为中心索引
思路:先统计出整个数组的总和,然后从第一个元素开始叠加
总和递减当前元素,叠加递增当前元素,知道两个值相等
删除排序数组中的重复项
一个有序数组 nums ,原地删除重复出现的元素,使每个元素只出现一次 ,返回删除后数组的新长度。不要使用额外的数组空间,必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。
双指针算法:
数组完成排序后,我们可以放置两个指针 i 和 j,其中 i 是慢指针,而 j 是快指针。只要nums[i]=nums[j],我们就增加 j 以跳过重复项。
当遇到 nums[j] != nums[i]时,跳过重复项的运行已经结束,必须把nums[j])的值复制到 nums[i +1]。然后递增 i,接着将再次重复相同的过程,直到 j 到达数组的末尾为止。
x的平方根
在不使用 sqrt(x) 函数的情况下,得到 x的平方根的整数部分
解法一:二分查找
x的平方根肯定在0到x之间,使用二分查找定位该数字,该数字的平方一定是最接近x的,m平方值如果大于x、则往左边找,如果小于等于x则往右边找
找到0和X的最中间的数m,
如果m * m > x,则m取x/2到x的中间数字,直到m * m < x,m则为平方根的整数部分如果m * m <= x,则取0到x/2的中间值,知道两边的界限重合,找到最大的整数,则为x平方根的整数部分
时间复杂度:O(logN)
解法二:牛顿迭代
假设平方根是 i ,则 i 和 x/i 必然都是x的因子,而 x/i 必然等于 i ,推导出 i + x / i = 2 * i,得出 i = (i +x / i) / 2
由此得出解法,i 可以任选一个值,只要上述公式成立,i 必然就是x的平方根,如果不成立, (i + x / i) /2得出的值进行递归,直至得出正确解
三个数的最大乘积
一个整型数组 nums ,在数组中找出由三个数字组成的最大乘积,并输出这个乘积。
乘积不会越界
如果数组中全是非负数,则排序后最大的三个数相乘即为最大乘积;如果全是非正数,则最大的三个数相乘同样也为最大乘积。
如果数组中有正数有负数,则最大乘积既可能是三个最大正数的乘积,也可能是两个最小负数(即绝对值最大)与最大正数的乘积。
分别求出三个最大正数的乘积,以及两个最小负数与最大正数的乘积,二者之间的最大值即为所求答案。
解法一:排序
解法二:线性扫描
两数之和
给定一个升序排列的整数数组 numbers ,从数组中找出两个数满足相加之和等于目标数 target 。
假设每个输入只对应唯一的答案,而且不可以重复使用相同的元素。
返回两数的下标值,以数组形式返回
暴力解法
时间复杂度:O(N的平方)
空间复杂度:O(1)
哈希表:将数组的值作为key存入map,target - num作为key
时间复杂度:O(N)
空间复杂度:O(N)
解法一:二分查找
先固定一个值(从下标0开始),再用二分查找查另外一个值,找不到则固定值向右移动,继续二分查找
时间复杂度:O(N * logN)
空间复杂度:O(1)
解法二:双指针
左指针指向数组head,右指针指向数组tail,head+tail > target 则tail 左移,否则head右移
时间复杂度:O(N)
空间复杂度:O(1)
斐波那契数列
求取斐波那契数列第N位的值。
斐波那契数列:每一位的值等于他前两位数字之和。前两位固定 0,1,1,2,3,5,8。。。。
解法一:暴力递归
解法二:去重递归
递归得出具体数值之后、存储到一个集合(下标与数列下标一致),后面递归之前先到该集合查询一次,如果查到则无需递归、直接取值。查不到再进行递归计算
解法三:双指针迭代
基于去重递归优化,集合没有必要保存每一个下标值,只需保存前两位即可,向后遍历,得出N的值
环形链表
给定一个链表,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达该节点,则链表中存在环如果链表中存在环,则返回 true 。 否则,返回 false 。
解法一:哈希表
解法二:双指针
排列硬币
总共有 n 枚硬币,将它们摆成一个阶梯形状,第 k 行就必须正好有 k 枚硬币。
给定一个数字 n,找出可形成完整阶梯行的总行数。
n 是一个非负整数,并且在32位有符号整型的范围内
解法一:迭代
从第一行开始排列,排完一列、计算剩余硬币数,排第二列,直至剩余硬币数小于或等于行数
解法二:二分查找
假设能排 n 行,计算 n 行需要多少硬币数,如果大于 n,则排 n/2行,再计算硬币数和 n 的大小关系
解法三:牛顿迭代
使用牛顿迭代求平方根,(x + n/x)/2
假设能排 x 行 则 1 + 2 + 3 + ...+ x = n,即 x(x+1)/2 = n 推导出 x = 2n - x
合并两个有序数组
两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使 nums1 成为一个有序数组。
初始化 nums1 和 nums2 的元素数量分别为 m 和 n 。假设 nums1 的空间大小等于 m + n,这样它就有足够的空间保存来自 nums2 的元素。
解法一:合并后排序
时间复杂度 : O((n+m)log(n+m))。
空间复杂度 : O(1)。
解法二:双指针 从前往后
将两个数组按顺序进行比较,放入新的数组
时间复杂度 : O(n + m)。
空间复杂度 : O(m)。
解法三:双指针优化
从后往前
时间复杂度 : O(n + m)。
空间复杂度 : O(1)。
子数组最大平均数
给一个整数数组,找出平均数最大且长度为 k 的下标连续的子数组,并输出该最大平均数。
滑动窗口:
窗口移动时,窗口内的和等于sum加上新加进来的值,减去出去的值
更多的算法笔记个刷题思路大家可以关注公众号:前程有光,免费获取完整版