这个系列没啥花头,就是纯 leetcode 题目拆解分析,不求用骚气的一行或者小众取巧解法,而是用清晰的代码和足够简单的思路帮你理清题意。让你在面试中再也不怕算法笔试。
50. 搜索二维矩阵 (search-a-2d-matrix)
标签
- 二分查找
- 中等
题目
这里不贴题了,leetcode打开就行,题目大意:
编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值。该矩阵具有如下特性:
每行中的整数从左到右按升序排列。- 每行的第一个整数大于前一行的最后一个整数。
输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3
输出:true
相关知识
数组拍平
Array.prototype.flat()
flat() 方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。
语法
var newArray = arr.flat([depth])
参数
depth (可选)
指定要提取嵌套数组的结构深度,默认值为 1。
例子
var arr1 = [1, 2, [3, 4]];
arr1.flat();
// [1, 2, 3, 4]
var arr2 = [1, 2, [3, 4, [5, 6]]];
arr2.flat();
// [1, 2, 3, 4, [5, 6]]
var arr3 = [1, 2, [3, 4, [5, 6]]];
arr3.flat(2);
// [1, 2, 3, 4, 5, 6]
//使用 Infinity,可展开任意深度的嵌套数组
var arr4 = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]];
arr4.flat(Infinity);
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
注意 flat() 方法会移除数组中的空项:
var arr4 = [1, 2, , 4, 5];
arr4.flat();
// [1, 2, 4, 5]
手动实现一层flat
var arr = [1, 2, [3, 4]];
// 展开一层数组
// 方法一: reduce + concat
arr.reduce((acc, val) => acc.concat(val), []);
// [1, 2, 3, 4]
// 方法儿: 使用扩展运算符 ...
const flattened = arr => [].concat(...arr);
手动实现无限层flat
// reduce + concat + 递归
var arr1 = [1,2,3,[1,2,3,4, [2,3,4]]];
function flatDeep(arr, d = 1) {
if (d > 0) {
return arr.reduce((acc, cur) => acc.concat(
Array.isArray(cur) ?
flatDeep(cur, d - 1) :
cur
), [])
} else {
return arr.slice();
}
};
console.log(flatDeep(arr1, Infinity));
// [1, 2, 3, 1, 2, 3, 4, 2, 3, 4]
基本思路
我们看到有序序列的查找问题,就想到可用二分查找。
不熟同学请移步 二分查找这篇先
基本步骤
- 先拍平成一维数组。
- 再二分查找就行了。
写法实现
var searchMatrix = function(matrix, target) {
// 先拍平,根据题意,拍平后是个有序一维数组
let matrixFlat = matrix.flat(Infinity);
// 有序数组查找,直接二分
let [left, right, mid] = [0, matrixFlat.length - 1, 0]
while (left <= right) {
mid = left + Math.floor((right - left) / 2)
console.log(mid, 'mid')
console.log(matrixFlat[mid])
if (matrixFlat[mid] === target) {
return true
} else if (matrixFlat[mid] > target) {
right = mid - 1
} else {
left = mid + 1
}
}
return false
};
let matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3
console.log(searchMatrix(matrix, target))
51. 颜色分类 (sort-colors)
标签
- 计数排序
- 中等
题目
这里不贴题了,leetcode打开就行,题目大意:
给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。
基本思路
这道题可以用计数排序,适合待排序数字很少的题目。
用一个 3 个容量的数组分别计数,记录 0,1,2 出现的次数。然后再根据个数排列 0,1,2 即可。
详细关于计数排序、桶排序和基数排序的原理请移步这篇文章:
基本步骤
请根据上面文章先了解计数排序的思想。
- 建立1个桶,里面就是放
0, 1, 2三个元素。
统计数 [0, 0, 0]
index [0, 1, 2]
- 遍历 nums 把这些元素分别装到桶里,其实就是用桶的
index位置来对应这三个数值,然后记录出现次数。 - 桶已经装完了,根据统计次数
放回原数组即可。
写法实现
var sortColors = function(nums) {
// 这题桶是一定的就三数,桶里元素表示这3数出现的次数
let [len, cur] = [nums.length, 0]
// 核心就是用index来对应这三个数
let bucket = [0, 0, 0]
nums.map(item => {
bucket[item]++
})
// 放回原数组
for (let i = 0; i < Math.max(len, 3); i++) {
while (bucket[i] > 0) {
nums[cur++] = i
// 用掉一次减一次
bucket[i]--;
}
}
return nums
};
let nums = [2,0,2,1,1,0]
console.log(sortColors(nums))
另外向大家着重推荐下这位大哥的文章,非常深入浅出,对前端进阶的同学非常有作用,墙裂推荐!!!核心概念和算法拆解系列
今天就到这儿,想跟我一起刷题的小伙伴可以加我微信哦
搜索我的微信号infinity_9368,可以聊天说地
加我暗号 "天王盖地虎" 下一句的英文,验证消息请发给我
presious tower shock the rever monster,我看到就通过,暗号对不上不加哈,加了之后我会尽我所能帮你,但是注意提问方式,建议先看这篇文章:提问的智慧