035 - 搜索插入位置(search-insert-position)
/*
* @Author: lvjingshuai
* @Date: 2019-07-21 06:21:12
* @Last Modified by: lvjingshuai
* @Last Modified time: 2019-08-16
*/
文章结构 |
---|
1、题目介绍 |
2、解题 |
2.1 解法 - for()循环 |
2.2 解法 - 二分查找法 |
3、每日一问 |
1、题目介绍
- 难度:简单 (系统学习算法与数据结构)
- 涉及知识:数组、二分查找
- 题目编号:035
- 题目地址:https://leetcode-cn.com/problems/search-insert-position/
- 题目内容:
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
你可以假设数组中无重复元素。
示例 1:
输入: [1,3,5,6], 5
输出: 2
示例 2:
输入: [1,3,5,6], 2
输出: 1
示例 3:
输入: [1,3,5,6], 7
输出: 4
示例 4:
输入: [1,3,5,6], 0
输出: 0
2、解题
- 官方题解:https://leetcode-cn.com/problems/search-insert-position/solution/te-bie-hao-yong-de-er-fen-cha-fa-fa-mo-ban-python-/
上面是官方使用 Java 进行的题解。
2.1 for()循环
解题思路:
这道题通过for遍历的话,情况判断
- 存在,即返回下标
- 不存在,且遍历的每一个item的值都小于目标值 即
nums[i] < target
, 插入数组的末尾 - 不存在,且遍历的每一个item的值都大于目标值 即
nums[i] > target
, 插入数组的头部 - 不存在,且遍历的item的值存在大于和小于target 即
nums[i]
中有满足target
插入的位置,返回插入位置的下标 - 其实最终的规律大家也都看出来了,即目标值大于等于item的值时,即为所求下标
解题代码:
var searchInsert = function(nums, target) {
for (let i = 0; i < nums.length; i++) {
if (nums[i] >= target) {
return i;
}
}
return nums.length;
};
执行测试:
nums
:[1, 3, 5, 6]
target
:2
return
:1
2.2 解法 - 二分法
解题思路:
-
我们需要了解的是,
一个数 / 2
,大概率返回的是小数,而我们的索引需要的是整数,所以我们通过Math.round()
来四舍五入获取整数。 -
就是
while
的逻辑判断: -
nums
:[1, 3, 5, 6]
-
target
:2
-
我们需要知道的是,如果
target
是2
,那么返回的[left, right]
是:[1, 0]
;如果target
是4
,那么返回的[left, right]
是[2, 1]
。因为循环结束的条件是left > right
,所以无疑left
是更接近中间值的。
解题代码:
var searchInsert = function(nums, target) {
let left = 0;
let right = nums.length - 1;
while (left <= right) {
let middle = Math.round((left + right) / 2);
// 等于的情况最简单,我们应该放在第 1 个分支进行判断
if (target === nums[middle]) {
return middle;
} else if (target < nums[middle]) {
right = middle - 1;
// middle 也一定不是所求的右边界
// 此时右边界更新为 middle - 1
} else if (target > nums[middle]) {
// 题目要我们返回大于或者等于目标值的第 1 个数的索引
// 此时 middle 一定不是所求的左边界,
// 此时左边界更新为 middle + 1
left = middle + 1;
}
}
// 注意:一定得返回左边界 left,
// 如果返回右边界 right 提交代码不会通过
// 【注意】下面我尝试说明一下理由,如果你不太理解下面我说的,那是我表达的问题
// 但我建议你不要纠结这个问题,因为我将要介绍的二分查找法模板,可以避免对返回 left 和 right 的讨论
// 理由是对于 [1,3,5,6],target = 2,返回大于等于 target 的第 1 个数的索引,此时应该返回 1
// 在上面的 while (left <= right) 退出循环以后,right < left,right = 0 ,left = 1
// 根据题意应该返回 left,
// 如果题目要求你返回小于等于 target 的所有数里最大的那个索引值,应该返回 right
return left;
};
执行测试:
nums
:[1, 3, 5, 6]
target
:2
return
:1
知识点:
-
“神奇的”
二分查找法
模板的基本思想:“排除法”
即:在每一轮循环中排除一半以上的元素,于是在对数级别的时间复杂度内,就可以把区间“夹逼”
只剩下 1 个数,而这个数是不是我们要找的数,单独做一次判断就可以了。 -
“夹逼法”
或者“排除法”
是二分查找算法
的基本思想,“二分”
是手段,在目标元素不确定的情况下,“二分”
也是“最大熵原理”
告诉我们的选择。 -
这道题在
二分
上要注意思考左
、右
边界,如果左
、右
边界不包括目标数值
,会导致错误结果 -
先写
二分
逻辑上容易想到的分支逻辑,这个分支逻辑通常是排除中位数的逻辑;
3、每日一题
webpack 的 常见的loader,常见的plugin?
webpack的定义:
webpack
是一个js
打包工具,在webpack里一切文件皆模块
,通过loader
转换文件,通过plugin
注入钩子,最后输出由多个模块组合成的文件。webpack
功能是分析你的项目结构
,找到JavaScript
模块以及其它的一些浏览器不能直接运行的拓展语言(Scss
,TypeScript
等),并将其打包
为合适的格式以供浏览器使用。
常见的loader:
file-loader
:把文件输出到一个文件夹中,在代码中通过相对 URL 去引用输出的文件url-loader
:和 file-loader 类似,但是能在文件很小的情况下以 base64 的方式把文件内容注入到代码中去source-map-loader
:加载额外的 Source Map 文件,以方便断点调试image-loader
:加载并且压缩图片文件babel-loader
:把 ES6 转换成 ES5css-loader
:加载 CSS,支持模块化、压缩、文件导入等特性style-loader
:把 CSS 代码注入到 JavaScript 中,通过 DOM 操作去加载 CSS。eslint-loader
:通过 ESLint 检查 JavaScript 代码
几个常见的plugin:
define-plugin
:定义环境变量terser-webpack-plugin
:通过TerserPlugin压缩ES6
代码html-webpack-plugin
为html
文件中引入的外部资源,可以生成创建html入口文件mini-css-extract-plugin
:分离css
文件clean-webpack-plugin
:删除打包文件happypack
:实现多线程加速编译