1、介绍
2、图的深度优先遍历
- 那么
深度优先遍历的怎么实现? - 方法论 咋们有了 那
怎么实现这个方法论呢 ?代码演示一下 - 新建一个图 graph.js
// 新建 一个图 邻接表表示法
// 后面 value表示 可以连接到的节点
const graph = {
0: [1, 2],
1: [2],
2: [0, 3],
3: [3],
};
//使可导出
module.exports = graph;
- dfs.js
const graph = require("./graph");
// 深度优先遍历
//建立一个新的集合 存放深度访问的节点 Set不允许重复
const visited = new Set();
const dfs = (n) => {
//访问根节点
console.log(n);
visited.add(n);
// 按照 属性进行节点遍历
graph[n].forEach((c) => {
if (!visited.has(c)) {
dfs(c);
}
});
};
dfs(2); // 2 0 1 3
-
当然 结果我已经显示在上面了 这次放在 node 环境执行一下
-
符合预期 说明 深度优先遍历 没有问题
3、图的广度优先遍历
- 来 学点新的东西 我保证你的趣味性十足
// 广度优先遍历方法展示
const graph = require("./graph");
const q = [2]; //新建队列 并将初始的节点传入
const visited = new Set(); //新建集合存放访问过的节点
visited.add(2); //添加初始值
while (q.length) {
const n = q.shift(); // 队头出队并访问
console.log(n); // 2 0 3 1
graph[n].forEach((c) => {
//遍历未访问的相邻节点
if (!visited.has(c)) {
q.push(c);
visited.add(c); // 这样可以防止将重复的节点 放入集合
}
});
}
- 先看一个 结果 虽然我上面展示出来了
4、leetcode 65 有效数字
- 这个题目比较难搞 属于困难部分
- 不过 这个题目只要能 给出这个 关系图 就好解决
/**
* @param {string} s
* @return {boolean}
* 1、新建图
* 2、建立的图的内容和实际判断对应上
* 3、新建状态 得到state = graph[state][c]
* 4、判断状态
* 时间复杂度 O(n) n指的是for循环的长度 空间复杂度为O(1) 因为有个图 但是它是固定大小的
*/
var isNumber = function(s) {
// 新建图
const graph = {
0:{'blank':0, '.':2,'sign':1, 'digit':6},
1:{'.':2, 'digit':6},
2:{'digit':3},
3:{'digit':3,'e':4,'E':4},
4:{'digit':5,'sign':7},
5:{'digit':5},
6:{'.':3,'e':4,'digit':6,'E':4},
7:{'digit':5}
}
// 需要一个记录到那里 状态的值
var state = 0
// 这个地方有个小技巧 前后去掉空格不影响结果
// 把自己写的和判断对应上
for(c of s.trim()){
if(c === ' '){
c = 'blank'
}else if(c >=0 && c <=9){
c = 'digit'
}else if(c === '+' || c === '-'){
c = 'sign'
}
// 更新状态
// 比如 graph[3][e] -->4
state = graph[state][c]
if(state === undefined){
return false
}
}
// 只有这三种情况才符合条件
if(state === 3 || state === 5 || state === 6){
return true
}
return false
};
-
nice 结果测试通过 你可以试试
5、leetcode 417 太平洋大西洋水流问题
- 感觉是不是很神奇
- 不要怕都是纸老虎
- 深度优先算法
/**
* @param {number[][]} matrix
* @return {number[][]}
* 时间复杂度 O(m*n) m n 二维循环 空间复杂度 O(m*n) 两个m*n矩阵 flow1 flow2
*/
var pacificAtlantic = function(matrix) {
//行数或列数如果为0,则返回空数组
if(!matrix||!matrix[0]) return [];
//数组的行数和列数
const m=matrix.length;
const n=matrix[0].length;
//初始化数组,用来记录太平洋和大西洋
const flow1=Array.from({length:m},()=>new Array(n).fill(false));
const flow2=Array.from({length:m},()=>new Array(n).fill(false));
//定义dfs方法
const dfs=(r,c,flow)=>{
flow[r][c]=true;
[[r-1,c],[r+1,c],[r,c+1],[r,c-1]].forEach(([nr,nc])=>{
if(
//保证在矩阵中
nr>=0&&nr<m&&
nc>=0&&nc<n&&
//防止死循环,一定要是没有访问过的
!flow[nr][nc]&&
//保证逆流而上
matrix[nr][nc]>=matrix[r][c]
){
//进行深度优先遍历
dfs(nr,nc,flow);
}
});
};
//调用dfs方法
//沿着海岸线逆流而上
for(let r=0;r<m;r++){
//左
dfs(r,0,flow1);
//右
dfs(r,n-1,flow2);
}
for(let c=0;c<n;c++){
//上
dfs(0,c,flow1);
//下
dfs(m-1,c,flow2);
}
//收集能流到两个大洋里的坐标
const res=[];
for(let r=0;r<m;r++){
for(let c=0;c<n;c++){
if(flow1[r][c]&&flow2[r][c]){
res.push([r,c]);
}
}
}
return res;
};
6、总结