原文位于 github仓库-正在起步阶段的前端知识库,其中记录了一名前端初学者的学习日记🤔&学习之路点点滴滴的记录(练手demo🧑💻,必会知识点🧐)
欢迎大家来贡献更多“前端er必会知识点”🧑🎓/分享更多有意义的demo❤️!(请给这个年幼的小仓库更丰富的内容吧🥺🥺🥺)
单纯针对数组来考察的题目,总体来说,都比较基础——数组题目要想往难了出,基本都要结合排序、二分和动态规划这些相对复杂的算法思想才行。
本篇记录那些“不那么难,但是面试中很高频且可以考验你数组掌握程度”的题目
-
不那么难,指的是这种题不需要用到困难的“解题技巧”,排序、二分思想、动态规划
-
面试中高频,字面意思,面试经常考嘛(虽说感觉前端er的面试中链表会问的比较多?)
-
考验数组掌握程度,这一点很重要,决定了面试官对你的看法——
- 你是个不求甚解所有题目都暴力求解的选手
- 还是会不断优化,充分利用数组API与一些简单技巧(例如双指针、哈希表)进行求解的选手?
下面开始 三道题入门数组题型,熟悉双指针技巧 涉及——
同向正序双指针
同向倒序双指针
反向对撞双指针
1. 两数之和
题目直通车 1. 两数之和
哈希表
暴力解就不放上来了,直接看使用哈希表优化之后的一趟求解法
几乎所有求和问题,都可以转化为求差问题,不知道i如何优化?试着想想求差~
-
借助哈希表一趟遍历解题
- 新建一个空对象模拟哈希表
var twoSum = function(nums, target) { let map = {}; for(let i = 0; i < nums.length; i++){ if(map[target - nums[i]] >= 0){ return [map[target - nums[i]], i]; } else{ map[nums[i]] = i; } } };- 另外这题里面Map数据结构真不咋好使滴(这API完全没帮上忙,还不如原生写法😂),还是直接创建一个对象,在对象里维护键值对儿吧~(也就是上面那个方法)
var twoSum = function(nums, target){
let map = new Map();
for(let i = 0; i < nums.length; i++){
if(map.get(target - nums[i]) >= 0){
return [i, map.get(target - nums[i])]
}
else{
map.set(nums[i], i);
}
}
}
88. 合并两个有序数组
同向正序双指针,同向倒序双指针
- 笨拙的暴力法 纯属是为了提高数组相关API的熟练度😂主站上逛了一圈没见过有这么写的
面试时可以试着用下来展示自己对数组这个数据结构的熟悉?hh
var merge = function(nums1, m, nums2, n) {
nums1.splice(m);
for(let j = 0; j < n; j++){
for(let i = 0; i < m + n; i++){
if(nums2[j] <= nums1[i]){
nums1.splice(i, 0, nums2[j]);
break;
}
if(nums2[j] > Math.max(...nums1)){
console.log(nums1)
nums1.push(...nums2.slice(j))
return nums1
}
}
}
// return nums1;// 如果走到这里 其实就不用return了哦
};
- 开辟新空间,常规双指针寻值
直接拿来官方题解的动图了 一目了然~
var merge = function(nums1, m, nums2, n) {
let p1 = 0, p2 = 0;
let temp = [];
while(p1 < m || p2 < n){
// 如果nums1/nums2已经遍历完了,那么只能操作另外一个数组了~
if(p1 === m){
temp.push(nums2[p2++]);
}
else if(p2 === n){
temp.push(nums1[p1++]);
}
// 较小的元素插入temp中(常规思路了这里~)
else if(nums1[p1] < nums2[p2]){
temp.push(nums1[p1++]);
}
else if(nums1[p1] >= nums2[p2]){
temp.push(nums2[p2++]);
}
}
for(let i = 0; i < m + n; i++){
nums1[i] = temp[i];
}
// return nums1; // 题目就让把nums1修改下,没必要return了哈~核心代码模式就是爽XD
};
- 不必开辟新空间,巧妙逆向双指针!
ppt过程模拟看这里
面试能答出来这么个倒序双指针,不得起飞咯😎(好吧这其实是基操。)
var merge = function(nums1, m, nums2, n) {
let p1 = m - 1, p2 = n - 1;
let tail = m + n - 1;
let cur;// 参考了官方题解,设置一个cur记录每次要去进行插入的值,更加清晰勒!
while(p1 >= 0 || p2 >= 0){
if(p1 === -1){
cur = nums2[p2--];
}
else if(p2 === -1){
cur = nums1[p1--];
}
else if(nums2[p2] > nums1[p1]){
cur = nums2[p2--];
}
else if(nums2[p2] <= nums1[p1]){
cur = nums1[p1--];
}
// 每次迭代找出应该挪到后面的元素
nums1[tail--] = cur;
}
};
15. 三数之和
反向对撞双指针
核心思想:对撞双指针 + 定指针分别挪动 & 保证获得的三个数不能重复(使用特殊判断跳过重复的值)
这里写了个题解 【JavaScript】对撞双指针 + 定指针 注释齐全
var threeSum = function(nums) {
// 先排个序~
nums = nums.sort((a, b) => {return a - b;})
let res = [];
// 定住的那个指针i
for(let i = 0; i < nums.length - 2; i++){
if(i >= 1 && nums[i - 1] === nums[i]){
// 如果重复 则跳过本次循环 直接返回for语句
continue;
}
// 每轮不断地动p1 p2来找答案
let p1 = i + 1;
let p2 = nums.length - 1;
while(p1 < p2){
let sum = nums[i] + nums[p1] + nums[p2];
if(sum === 0){
res.push([nums[i], nums[p1], nums[p2]]);
// 找到一个答案,接着进行寻找,注意不要造成重复!
// (第一次做就在这里不断错!其实想清楚还是很简单的——)
p1++;
while(nums[p1] === nums[p1 - 1]){
p1++;
}
p2--;
while(nums[p2] === nums[p2 + 1]){
p2--;
}
}
// 挪动双指针,为了防止重复,要跳过重复值
else if(sum < 0){
p1++;
// 注意这里当新p1与上一个p1相同时 才会加
while(nums[p1] === nums[p1 - 1]){
p1++;
}
}
else if(sum > 0){
p2--;
// 注意这里当新p2与上一个p2相同时 才会减
while(nums[p2] === nums[p2 + 1]){
p2--;
}
}
// 一头一尾两个指针一轮的挪动完毕
}
}
return res;
};