大厂算法面试之 leetcode 精讲 19. 数组
搞定大厂算法面试之 leetcode 精讲 19.数组
视频讲解(高效学习):点击学习
目录:
数组操作的时间复杂度
Access:
O(1)
Search:
O(n)
Insert: 平均
O(n)
,最好的情况下O(1)
,也就是在数组尾部插入O(1)
,最坏的情况下O(n)
Delete;平均
O(n)
,最好的情况下O(1)
,也就是在数组尾部删除O(1)
,最坏的情况下O(n)
283. 移动零 (easy)
方法 1:两次遍历
思路:遍历数组,定义索引 j 为数组的第一个位置,遇上非 0 元素,让 j 位置上的元素等于这个非 0 元素,遍历完数组之后,j 位置之后的元素全部置为 0
复杂度:时间复杂度
O(n)
,空间复杂度O(1)
js:
java:
方法 2:双指针一次遍历
思路:定义 left、right 指针,right 从左往右移动,遇上非 0 元素,交换 left 和 right 对应的元素,交换之后
left++
复杂度:时间复杂度
O(n)
,空间复杂度O(1)
js:
java:
75. 颜色分类 (medium)
方法 1.双指针
思路:准备 p0,p1 两个指针,p0 指向 0 元素,p1 指向 1,初始化的时候,两个指针都指向数组的第一个位置。然后循环数组
遇见 1 就交换当前元素和 p1,让 p1 加 1,向前移动一位
遇见 0 就交换当前元素和 p0,如果 p1 小于 p0,则此时 p0 指向的元素是 1,与 i 位置元素交换之后 这个交换过去的 1 位置就不对了,所以交换过去的 1 需要在和 p1 交换一下,这时 p0 和 p1 都指向了正确的元素,所以都需要向前移动一次。如果 p0 等于 p1,则前面的元素都是 0,所以 p0 和 p1 也要向前移动一次
复杂度:时间复杂度
O(n)
,n 是数组的长度,空间复杂O(1)
js:
java
方法 2.双指针
思路:准备两指针,p0 指向元素 0,它左边的都是 0,p2 指向 2,它右边都是 2,然后循环数组,当循环到了 p2,说明 p2 右边的元素都是正确的数,所以
i<=p2
如果此时 i 指向元素 2 i 小于 p2 则不断交换 p2 和 i 指向的元素 因为交换过来的数可能还是 2,那这个 2 就处于不正确的位置了
如果此时 i 指向元素 0 则交换 p0 和 i 指向的元素
循环完成则 0 和 2 都拍好了,中间的 1 自然也是正确的位置
复杂度:时间复杂度
O(n)
,n 是数组的长度,空间复杂O(1)
js:
java
167. 两数之和 II - 输入有序数组 (easy)
方法 1:二分法
思路:循环数组,从当前元素右边的元素二分查找另一个元素,使他们的和是
target
复杂度:时间复杂度
O(nlogn)
,遍历数组,每次遍历都进行了二分。空间复杂度O(1)
js:
java:
方法 2:双指针
思路:应以 left 和 right 指针,初始分别在数组的两端,然后不断判断两个指针指向的数字之和 和 target 的大小,和大了 ,right 左移一位,和小了,left 右移一位
复杂度:时间复杂度
O(n)
,数组总共遍历一次。空间复杂度O(1)
js:
java
209. 长度最小的子数组 (medium)
方法 1:滑动窗口
思路:左右指针是滑动窗口的两边,用滑动窗口循环数组,不断扩大窗口,如果窗口中元素的和大于 target,就开始缩小窗口,然后更新最小滑动窗口
复杂度:时间复杂度
O(n)
,数组中的元素都遍历一次,空间复杂度O(1)
js:
java:
349. 两个数组的交集 (easy)
方法 1:集合
思路:先将数组转成 set,然后遍历长度小的 set,判断 set1 中的元素是否存在于 set2 中,存在的话就是其中一个交集。
复杂度:时间复杂度
O(m+n)
,m,n 是两数组的长度,数组转成集合的时间复杂度就是数组的长度,遍历寻找交集的复杂度是O(min(m,n))
。空间复杂度O(m+n)
,就是两个 set 的空间
js:
java:
方法 2:排序+双指针
思路:数组排序,然后用两个指针分别遍历数组,如果两个指针指向的元素相等 就是其中一个交集,否则比较两个指针指向的元素的大小,较小的向前移动
复杂度:时间复杂度
O(mlogm+nlogn)
,两数组快排时间复杂度分别是O(mlogm)
、O(nlogn)
,双指针遍历需要O(m+n)
,复杂度取决于较大的O(mlogm+nlogn)
。空间复杂度O(logm+logn)
排序使用的额外空间
js:
Java;
350. 两个数组的交集 II (easy)
方法 1:哈希表
思路:统计 nums1 中各个元素的频次,循环 nums2,看 nums2 中的元素是否在 mums1 频数哈希表中存在,存在的话加入结果,并且频数减 1
复杂度:时间复杂度
O(m+n)
,遍历两个数组,哈希表操作复杂度是O(1)
。空间复杂度O(min(m,n))
对长度小的数组进行哈希。
js:
java:
方法 2:双指针
思路:p1,p2 双指针指向两数组中的元素,在 p1,p2 都不越界的情况下开始循环,如果 p1 指向的元素大,移动 p2,如果 p2 指向的元素大,移动 p1,遇到相同则加入入 res,移动两指针
复杂度:时间复杂度
O(mlogm+nlogn)
,m、n 分别是数组的长度,排序时间复杂度是O(mlogm+nlogn)
,两数组遍历是O(m+n)
。空间复杂度O(logm+logn)
js:
java:
27. 移除元素 (easy)
思路:用双指针遍历数组,left 初始化在 0 号位置,right 初始化在
nums.length
的位置,当left<right
的时候循环数组当
nums[left] === val
的时候,用 right-1 的位置覆盖 left 的位置指向的元素,然后向左移动 right当 nums[left] !== val 的时候,说明当前元素不需要覆盖,直接让
left++
复杂度:时间复杂度
O(n)
,数组遍历一遍。空间复杂度O(1)
js:
java:
217. 存在重复元素 (easy)
方法 1.排序
思路:先排序,然后循环数组,判断相邻元素是否相同
复杂度:时间复杂度
O(nlogn)
,空间复杂度O(logn)
,排序需要的栈空间
js:
java:
方法 2.哈希表
思路:循环数组,将元素存入 set,判断每个元素是否存在于 set 中
复杂度:时间复杂度
O(n)
,空间复杂度O(n)
js:
java:
238. 除自身以外数组的乘积 (medium)
思路:从左往右遍历,记录从左到当前位置前一位的乘积,然后从右往左遍历,从左到当前位置前一位的乘积乘上右边元素的积。
复杂度:时间复杂度
O(n)
,空间复杂度O(1)
js:
java
905. 按奇偶排序数组 (easy)
方法 1.排序
思路:排序比较,偶数在前,奇数在后
复杂度:时间复杂度
O(nlogn)
,空间复杂度O(logn)
,排序额外的空间
js:
方法 2.双指针
思路:右指针从右往左,直到遇到第一个偶数,左指针从左往右,直到遇到第一个奇数,然后交换位置
复杂度:时间复杂度
O(n)
,空间复杂度O(1)
js:
java:
922. 按奇偶排序数组 II (easy)
方法 1.双指针
思路:循环偶数位置 如果遇到了奇数,然后循环奇数位置 如果遇到了第一个偶数,就交位
复杂度:时间复杂度
O(n)
,空间复杂度O(1)
js:
java:
评论