前言
本篇作为小编总结算法的开端,后续会做成系列。算法体现一个人的思维能力,对程序员至关重要。
评估标准
时间复杂度
定义
定性来描述该算法的运行时间,用O表示。布吉岛大家还是否记得高中的让我们头疼的各种函数:二次、三次、幂函数、指数函数、log函数、各种组合函数...... 没错! 就是一直陪伴我们学习和工作的她们。不好依稀,俺还记得,但是呢如果大家不清楚原理了,那就生猛一些吧,把下面的图印在脑海~
二维图
ps: 看过之后是不是头大了,这是啥!哈哈,跟大家开个玩笑,如果你真的记不住那我们只需要记住简单的几个就可以啦,如下:
- O(1):代表只执行一次,没有任何循环
let i = 0;
i += 1 //只执行了一次
- O(n):循环,执行了n次
for(let i = 0; i < n; i += 1) {
//DO SOMETHIGN
}
- O(1) + O(n) = O(n);
let i = 0;
i += 1;
for(let i = 0; i < n; i += 1) {
//DO SOMETHING
}
- O(n) * O(n) = O(n^2)
for(let i = 0; i < n; i += 1) {
for(let j = 0; j < n; i += 1) {
// DO SOMETHING
}
}
- O(logN)
let i = 1;
while(i < n) {
i *= 2
//DO SOMETHING
}
空间复杂度
定义
算法在运行过程中临时占用存储空间大小的量度
示例
- O(1)
let i = 0;
i += 1;
- O(n)
const list = [];
for(let i = 0; i < n; i +=) {
list.push(i);
}
- O(n^2) 其实就是我们学的线性代数中的矩阵,而在前端是用数组来表示,存储了2^n个变量
const matrix = [];
for(let i = 0; i < n; i += 1) {
matrix.push([])
for(let j = 0; j < n; j += 1) {
matrix[i].push(j);
}
}
数据结构
栈(单调栈)
基本的栈的概念在这里就不细聊了,单调栈的含义就是栈内的元素是单调的(就是成正比或反比),下面的题目是递减栈,我们依次将元素压入栈,如果当前元素小于等于栈顶元素则入栈,如果大于栈顶元素则将栈顶不断出栈,直到当前元素小于或者等于栈顶元素为止,再将当前元素入栈。就比如下图的4,想入栈的话则需要2,3出栈之后才能入栈,因为4大于他俩。
示意图
应用场景
下一个更大元素
来源:力扣(LeetCode)
给你两个 没有重复元素 的数组 nums1 和 nums2 ,其中nums1 是 nums2 的子集。
请你找出 nums1 中每个元素在 nums2 中的下一个比其大的值。
nums1 中数字 x 的下一个更大元素是指 x 在 nums2 中对应位置的右边的第一个比 x 大的元素。如果不存在,对应位置输出 -1 。
示例 1:
输入: nums1 = [4,1,2], nums2 = [1,3,4,2].
输出: [-1,3,-1]
解释:
对于 num1 中的数字 4 ,你无法在第二个数组中找到下一个更大的数字,因此输出 -1 。
对于 num1 中的数字 1 ,第二个数组中数字1右边的下一个较大数字是 3 。
对于 num1 中的数字 2 ,第二个数组中没有下一个更大的数字,因此输出 -1 。
思路:其实就是将num2中的数据形成一个哈希映射,最后遍历num1
var nextGreaterElement = function(nums1, nums2) {
// 先创建一个栈
const stack = [nums2[0]];
const map = new Map();
nums2.slice(1).forEach((value) => {
if(value > stack[stack.length - 1]) {
while(value > stack[stack.length - 1]){
map.set(stack.pop(), value);
}
stack.push(value)
}else {
stack.push(value)
}
})
return nums1.map((v, i) => map.get(v) ? map.get(v) : -1)
// nums2[1] > nums[0] //直到满足此条件, nums[0]代表栈顶,nums[1]代表新元素
// stack.pop(); //将栈循环清空,并依次map.set(栈中元素, 新元素)
// map.set(nums[0], nums[1])
// nums2[1] <= nums[0];
// stack.push(nums2[1]); //循环判断此逻辑,满足条件便push
}
ps: 既然能存到栈顶,说明比下面的数字小,那就是不是其对应的映射数字。
接雨水
javascript题解
/**
* @param {number[]} height
* @return {number}
*/
var trap = function(height) {
let left = 0;
let right = height.length - 1;
let res = 0;
let leftMax = 0;
let rightMax = 0;
while (left < right) {
if (height[left] < height[right]) {
leftMax = Math.max(height[left], leftMax);
res += leftMax - height[left];
left++;
} else {
rightMax = Math.max(height[right], rightMax);
res += rightMax - height[right];
right--;
}
}
return res;
};
这部分原理比较复杂,建议看这里 : leetcode-cn.com/problems/tr…
当然最简单的方案是双指针法,也是我们必须要掌握的,算法篇下一节会细讲(并会以接雨水为例)。