零 标题:算法(leetode,附思维导图 + 全部解法)300题之(41)缺失的第一个正数
一 题目描述
二 解法总览(思维导图)
三 全部解法
1 方案1
1)代码:
// 方案1 “无视要求,去重、排序、过滤 - 暴力法”
// 技巧:“有序胜过无序”。
// 通过sort方法(时间复杂度仅为 O(nlogn))将无序的数组变有序是一件很划算的事情。
// 思路:
// 1)状态初始化。nums 去重、升序排列 并 只保留正整数部分
// 2)遍历 nums
// 2.1)若 此时 nums[i] 和 resNum 不相等,则 退出循环
// 2.2)否则 resNum++
// 3)返回结果 resNum
var firstMissingPositive = function(nums) {
// 1)状态初始化。nums 去重、升序排列 并 只保留正整数部分
const l = nums.length;
nums = [...new Set(nums)];
nums = nums.sort((a, b) => a - b).filter(item => item > 0);
let resNum = 1;
// 2)遍历 nums
for (let i = 0; i < l; i++) {
// 2.1)若 此时 nums[i] 和 resNum 不相等,则 退出循环
if (nums[i] !== resNum) {
break;
}
// 2.2)否则 resNum++
else {
resNum++;
}
}
// 3)返回结果 resNum
return resNum;
}
2 方案2
1)代码:
// 方案2 “无视题目要求 - 哈希法(JS里的 Map数据结构 )”。
// 注:目前实现的 时间、空间复杂度都是 O(n),不符合题目要求 —— “时间复杂度为 O(n) 并且只使用常数级别额外空间” 。
// 思路:
// 1)状态初始化:map = new Map(), resVal = 1 。
// 2)核心1:遍历 nums 。
// 2.1)若 当前 nums[i] 值大于0(即 为正整数),则 将其放入 map 中。
// 3)核心2:循环,只要此时 resVal 小于 l + 1(注:这里的边界是 l + ,例子:[1])。
// 3.1)若 此时的resVal 不存在于 map 中,则 退出循环 。
// 3.2)若 此时的resVal 不存在于 map 中,则 退出循环 。
// 4)返回结果 resVal 。
var firstMissingPositive = function(nums) {
// 1)状态初始化:map = new Map(), resVal = 1 。
const l = nums.length;
let map = new Map(),
resVal = 1;
// 2)核心1:遍历 nums 。
for (let i = 0; i < l; i++) {
// 2.1)若 当前 nums[i] 值大于0(即 为正整数),则 将其放入 map 中。
const tempVal = nums[i];
if (tempVal > 0) {
// 注:这里的 1(可换任何值) 起标记作用、 无意义!
map.set(tempVal, 1);
}
}
// 3)核心2:循环,只要此时 resVal 小于 l + 1(注:这里的边界是 l + ,例子:[1])。
while (resVal < l + 1) {
// 3.1)若 此时的resVal 不存在于 map 中,则 退出循环 。
if (!map.has(resVal)) {
break;
}
// 3.2)若 此时的resVal 不存在于 map 中,则 退出循环 。
else {
resVal++;
}
}
// 4)返回结果 resVal 。
return resVal;
}
3 方案3
1)代码:
// 方案3 “置换法”。
// 参考:
// 1)https://leetcode-cn.com/problems/first-missing-positive/solution/que-shi-de-di-yi-ge-zheng-shu-by-leetcode-solution/
// 思路:
// 1)状态初始化:resVal resVal = l + 1 。
// 2)遍历 nums 。
// 2.1)若 nums[i] 值在 范围 [0, l - 1] 且 nums[nums[i] - 1] 不等于 nums[i],
// 则 不断(“需循环处理!!”)交换下标 nums[i] - 1 和 i 上的值。
// 3)遍历 nums 。
// 3.1)若 此时的 nums[i] 不等于 i + 1 ,则 resVal 置为 i + 1 并 退出循环处理。
// 4)返回结果 resVal 。
var firstMissingPositive = function(nums) {
// 1)状态初始化:resVal resVal = l + 1 。
const l = nums.length;
let resVal = l + 1;
// 2)遍历 nums 。
for (let i = 0; i < l; i++) {
// 2.1)若 nums[i] 值在 范围 [0, l - 1] 且 nums[nums[i] - 1] 不等于 nums[i],
// 则 不断(“需循环处理!!”)交换下标 nums[i] - 1 和 i 上的值。
while (nums[i] > 0 && nums[i] <= l && nums[nums[i] - 1] !== nums[i]) {
[nums[nums[i] - 1], nums[i]] = [nums[i], nums[nums[i] - 1]];
}
}
// 3)遍历 nums 。
for (let i = 0; i < l; i++) {
// 3.1)若 此时的 nums[i] 不等于 i + 1 ,则 resVal 置为 i + 1 并 退出循环处理。
if (nums[i] !== i + 1) {
resVal = i + 1;
break;
}
}
// 4)返回结果 resVal 。
return resVal;
}
四 资源分享 & 更多
1 历史文章 - 总览
2 【资源分享】算法通关 + 面试宝典
1)算法通关40讲(极客 - 外企大佬讲的):
链接: https://pan.baidu.com/s/1C175QEmcAunjnCzYzoLBz 提取码: hjna
2)动态规划专题(价值几百美刀~):https://www.bilibili.com/video/BV1nt4y1Y7nz
3)前端面经:
3.1)https://www.nowcoder.com/tutorial/96
3.2)https://muyiy.cn/question
3.3)https://hub.fastgit.org/haizlin/fe-interview/blob/master/category/history.md
注:若失效请前往VX公众号: 码农三少 ,发送关键字: LeetCode 或 算法 ,即可获取最新的链接~
3 博主简介
码农三少 ,一个致力于编写 极简、但齐全题解(算法) 的博主。
专注于 一题多解、结构化思维 ,欢迎一起刷穿 LeetCode ~