学算法认准 labuladong
点击卡片可搜索文章👇
之前发布了算法可视化面板之后,有很多读者希望能够在可视化面板运行自己的代码。最近给我的算法学习网站自建了后端服务,可视化面板添加了编辑器功能,可以输入自定义代码了,可视化面板地址:
https://labuladong.online/algo-visualize
本文就简单介绍一下可视化编辑器的基本用法,更多功能尽请期待,欢迎大家体验和反馈问题。由于公众号的限制,无法在页面嵌入交互式教程,可以在电脑浏览器查看交互式教程。
编辑器交互式使用教程(本文):
https://labuladong.online/algo/intro/visualize-editor/
算法可视化实用技巧交互式教程:
https://labuladong.online/algo/intro/visualize/
运行自定义代码比较消耗计算资源,所以可视化服务对用户的行为限制较严格,正常使用不会出现问题,但不要用程序恶意请求后端 API,否则会被自动封号。如遇到误封的情况请留言。
只需微信扫码即可登录使用可视化面板,点击「编辑」按钮后可以输入并提交你的算法代码进行可视化:
目前只支持 JavaScript 语言,后续计划支持 Python 语言,但是现在 AI 这么厉害,改写一下语言应该的不算什么困难的,对吧。
编辑器如何使用呢?
简单说,像数组哈希表这种编程语言内置的数据结构,就按照正常编程的用法即可,对于力扣特有的比如 ListNode, TreeNode
之类的数据结构,用法和力扣保持一致。
除了数据结构操作的可视化,还支持用 @visualize
标签 对递归算法进行可视化,大幅降低读者理解递归算法的难度。
下面就简单介绍一下可视化面板编辑器的使用方法。
操作内置数据结构
类似数组、哈希表等 JavaScript 内置的数据结构,就正常初始化和操作它们即可,比如:
需要着重讲的是 力扣/LeetCode 中一些特殊的数据结构,比如单链表ListNode
和二叉树TreeNode
,它们的基本定义和用法和力扣上一样,下面提供一些例子。
操作单链表
首先说一下单链表,你可以用ListNode.create
方法快速创建一条单链表,这是一个简单的例子:
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
// 创建两条单链表
let head1 = ListNode.create([1, 4, 3, 2, 8]);
let head2 = ListNode.create([5, 6]);
// 遍历单链表
let arr = []
for (let p = head1; p !== null; p = p.next) {
arr.push(p.val);
}
// 把第二条链表接到第一条链表的中间
head2.next.next = head1.next.next.next;
// 当然,你也可以手动组装链表
let node1 = new ListNode(1);
let node2 = new ListNode(2);
node1.val = 66
// node1 -> node2
node1.next = node2;
// node3 -> node1 -> node2
let node3 = new ListNode(3, node1);
单链表的每个节点有val, next
属性,和力扣上的定义完全一致。
操作二叉树
再说一下二叉树,你可以用TreeNode.create
方法快速创建一棵二叉树。注意我们用列表来表示二叉树,表示方式和 力扣题目中表示二叉树的方式 相同,这里举两个例子:
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
let root1 = TreeNode.create([3,9,20,null,null,15,7])
let node = root1.right.left;
let nodeVal = node.val;
node.val = 99;
// 当然,你也可以手动组装二叉树节点
let leftNode = new TreeNode(2);
let rightNode = new TreeNode(3);
let root2 = new TreeNode(1, null, rightNode);
root2.left = leftNode;
每个二叉树节点有val, left, right
属性,和力扣上的定义完全一致。
操作多叉树
多叉树的节点定义和表示方法也和力扣完全一致,可以用Node.create
来创建多叉树。
大家主要注意一下多叉树的表示方法,我们还是用列表来表示多叉树,使用层序遍历的顺序,并用null
来分割每组子节点,具体可以参考这道力扣题目 429. N 叉树的层序遍历 的示例。
/**
* // Definition for a Node.
* function Node(val, children) {
* this.val = val;
* this.children = children;
* };
*/
let root1 = Node.create([1,null,3,2,4,null,5,6])
let node = root1.children[0].children[1]
let nodeVal = node.val
node.val = 99
// 当然,你也可以手动组装多叉树节点
let children = [new Node(2), new Node(3), new Node(4)]
let root2 = new Node(1, children);
每个多叉树节点有val, children
属性,和力扣上的定义完全一致。
可视化递归过程
我的可视化面板的一大特色,就是结合之前讲解的 学习数据结构和算法的框架思维,把递归过程可视化出来,帮助读者理解递归过程。具体的效果和使用技巧可以看 在网站/插件中使用可视化面板,我这里只说明如何在编辑器中开启递归过程的追踪。
核心就在于在你的递归函数上加上@visualize
注释,比如这个斐波那契数列的例子:
// @visualize status(n)
var fib = function(n) {
if (n < 2) {
return n;
}
return fib(n - 1) + fib(n - 2);
}
let result = fib(5)
具体的含义是:
1、对这个fib
函数开启递归树可视化功能,每次递归调用会被可视化为递归树上的一个节点,函数参数中的n
的值会显示在节点上。
2、如果函数有返回值,那么当函数结束,计算出某个节点返回值时,鼠标移动到这个节点上,会显示该返回值。
3、fib
函数被视为一个遍历这棵递归树的指针,处于堆栈路径的树枝会加粗显示。
使用 @visualize 的注意事项:
1、定义函数时,需要使用
var fib = function(n) { ... }
的方式,不要使用function fib(n) { ... }
的方式,否则无法追踪递归过程。2、
@visualize
注释必须写在函数定义的上一行,否则无法追踪递归过程。
再举个回溯算法的例子,根据 回溯算法核心框架,我们可以把track
列表可视化出来观察回溯过程:
var permuteRepeat = function(nums) {
let res = [];
let track = [];
backtrack(nums, track, res);
return res;
}
// 把 track 的变化可视化到递归树上
// @visualize status(track)
var backtrack = function(nums, track, res) {
// 触发结束条件
if (track.length === nums.length) {
res.push([...track]); // 将列表添加到result中
return;
}
for (let i = 0; i < nums.length; i++) {
// 做选择
track.push(nums[i]);
// 进入下一层决策树
backtrack(nums, track, res);
// 取消选择
track.pop();
}
}
let result = permuteRepeat([1, 2, 3]);
当然,根据 从二叉树彻底理解一切递归算法 所讲,回溯算法属于二叉树遍历的思路,backtrack
函数没有返回值,所以鼠标移动道节点上也不会显示返回值。
最后
欢迎大家使用可视化面板/编辑器学习算法,如果遇到问题或者 bug,可以直接在本文下方留言。
可视化编辑器正在和我的 Chrome 配套插件、VSCode 配套插件 以及 JetBrains 配套插件 整合。另外,我还做了一些实用有趣的小东西在内测,后续正式上线后再在公众号通知大家,敬请期待~