算法-链表树

链表

反转单向链表

  • 该题⽬来⾃ LeetCode,题⽬需要将⼀个单向链表反转。思路很简单,使⽤三个变量分别表示当前节点和当前节点的前后节点,虽然这题很简单,但是却是⼀道⾯试常考题
var reverseList = function(head) {
// 判断下变量边界问题
if (!head || !head.next) return head
// 初始设置为空,因为第⼀个节点反转后就是尾部,尾部节点指向 null
let pre = null
let current = head
let next
// 判断当前节点是否为空
// 不为空就先获取当前节点的下⼀节点
// 然后把当前节点的 next 设为上⼀个节点
// 然后把 current 设为下⼀个节点,pre 设为当前节点
while(current) {
next = current.next
current.next = pre

⼆叉树的先序,中序,后序遍历

  • 先序遍历表示先访问根节点,然后访问左节点,最后访问右节点。
  • 中序遍历表示先访问左节点,然后访问根节点,最后访问右节点。
  • 后序遍历表示先访问左节点,然后访问右节点,最后访问根节点

递归实现

  • 递归实现相当简单,代码如下
pre = current
current = next
}
return pre
};
function TreeNode(val) {
this.val = val;
this.left = this.right = null;
}
var traversal = function(root) {
if (root) {
// 先序
console.log(root);
traversal(root.left);
// 中序
// console.log(root);
traversal(root.right);
// 后序
// console.log(root);
}
};
  • 对于递归的实现来说,只需要理解每个节点都会被访问三次就明⽩为什么这样实现了

⾮递归实现

  • ⾮递归实现使⽤了栈的结构,通过栈的先进后出模拟递归实现。
以下是先序遍历代码实现
function pre(root) {
if (root) {
let stack = [];
// 先将根节点 push
stack.push(root);
// 判断栈中是否为空
while (stack.length > 0) {
// 弹出栈顶元素
root = stack.pop();
console.log(root);
// 因为先序遍历是先左后右,栈是先进后出结构
// 所以先 push 右边再 push 左边
if (root.right) {
stack.push(root.right);
}
if (root.left) {
stack.push(root.left);
}
}
}
}
以下是中序遍历代码实现
function mid(root) {
if (root) {
let stack = [];
// 中序遍历是先左再根最后右
// 所以⾸先应该先把最左边节点遍历到底依次 push 进栈
// 当左边没有节点时,就打印栈顶元素,然后寻找右节点
// 对于最左边的叶节点来说,可以把它看成是两个 null 节点的⽗节点
// 左边打印不出东⻄就把⽗节点拿出来打印,然后再看右节点
while (stack.length > 0 || root) {
if (root) {
stack.push(root);
root = root.left;
} else {
root = stack.pop();
console.log(root);
root = root.right;
}
}
  • 以下是后序遍历代码实现,该代码使⽤了两个栈来实现遍历,相⽐⼀个栈的遍历来说要容易理解很多
function pos(root) {
if (root) {
let stack1 = [];
let stack2 = [];
// 后序遍历是先左再右最后根
// 所以对于⼀个栈来说,应该先 push 根节点
// 然后 push 右节点,最后 push 左节点
stack1.push(root);
while (stack1.length > 0) {
root = stack1.pop();
stack2.push(root);
if (root.left) {
stack1.push(root.left);
}
if (root.right) {
stack1.push(root.right);
}
}
while (stack2.length > 0) {
console.log(s2.pop());
}
}
}

中序遍历的前驱后继节点

  • 实现这个算法的前提是节点有⼀个 parent 的指针指向⽗节点,根节点指向null
  • 该树的中序遍历结果是 4, 2, 5, 1, 6, 3, 7

前驱节点

  • 对于节点 2 来说,他的前驱节点就是 4 ,按照中序遍历原则,可以得出以下结论
  • 如果选取的节点的左节点不为空,就找该左节点最右的节点。对于节点 1 来说,他有左节点 2 ,那么节点 2 的最右节点就是 5
  • 如果左节点为空,且⽬标节点是⽗节点的右节点,那么前驱节点为⽗节点。对于节点 5 来说,没有左节点,且是节点 2 的右节点,所以节点 2 是前驱节点
  • 如果左节点为空,且⽬标节点是⽗节点的左节点,向上寻找到第⼀个是⽗节点的右节点的节点。对于节点 6 来说,没有左节点,且是节点 3 的左节点,所以向上寻找到节点 1 ,发现节点 3 是节点 1 的右节点,所以节点 1 是节点 6 的前驱节点
以下是算法实现
function predecessor(node) {
if (!node) return
// 结论 1
if (node.left) {
return getRight(node.left)
} else {
let parent = node.parent
// 结论 2 3 的判断
while(parent && parent.right === node) {
node = parent
parent = node.parent
}
return parent
}
}
function getRight(node) {
if (!node) return
node = node.right
while(node) node = node.right
return node
}

后继节点

  • 对于节点 2 来说,他的后继节点就是 5 ,按照中序遍历原则,可以得出以下结论
  • 如果有右节点,就找到该右节点的最左节点。对于节点 1 来说,他有右节点 3 ,那么节点3 的最左节点就是 6
  • 如果没有右节点,就向上遍历直到找到⼀个节点是⽗节点的左节点。对于节点 5 来说,没有右节点,就向上寻找到节点 2 ,该节点是⽗节点 1 的左节点,所以节点 1 是后继节点 以
    下是算法实现
function successor(node) {
if (!node) return
// 结论 1
if (node.right) {
return getLeft(node.right)
} else {
// 结论 2
let parent = node.parent
// 判断 parent 为空
while(parent && parent.left === node) {
node = parent
parent = node.parent
}
return parent
}
}
function getLeft(node) {
if (!node) return
node = node.left
while(node) node = node.left
return node
}

树的深度

  • 树的最⼤深度:该题⽬来⾃ Leetcode,题⽬需要求出⼀颗⼆叉树的最⼤深度
  • 以下是算法实现
var maxDepth = function(root) {
if (!root) return 0
return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1
};
  • 对于该递归函数可以这样理解:⼀旦没有找到节点就会返回 0,每弹出⼀次递归函数就会加⼀,树有三层就会得到3

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/26444.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WSL安装

WSL安装 1.Microsoft store 安装 1.1 启动WSL功能 在【程序和功能 -> 启用或关闭 Windows 功能】中勾选【适用于 Linux 的 Windows 子系统】 1.2 Store中下载安装 在 Microsoft Store 中下载并安装需要的 Linux 发行版 2.不使用Store安装WSL 注:1.1也要…

js执行机制

JavaScript 的执行机制是基于单线程的事件循环模型。这意味着 JavaScript 代码会按照顺序一行一行地执行,同时只能执行一个任务。让我们更详细地了解 JavaScript 的执行机制: 调用栈(Call Stack): JavaScript 使用调用…

激活函数总结(一):ReLU及其变体

激活函数介绍(一) 1 引言2 常用激活函数介绍2.1 Sigmoid激活函数2.2 Tanh激活函数2.3 ReLU激活函数2.4 Leaky ReLU激活函数2.5 Parametric ReLU(PReLU)激活函数2.6 Swish激活函数 3. 总结 介绍的激活函数都在目录中有所展示&#…

Mysql删除重复数据通用SQL

在日常开发过程中,可能会出现一些 bug,导致 Mysql 数据库数据重复,需要删除重复数据,这里记录下删除重复数据的通用 SQL ,方便以后需要时查阅 1、写法一 DELETE t1 FROMtbl_name t1 INNER JOIN tbl_name t2 WHEREt1.…

强人工智能转向超人工智能的突破点(猜测)

现如今,人类已经能够借助大量的资源,完成强人工智能。可能向大家接触到的X-EVA之类的APP,里面的虚拟人类有时候会说话五迷三道的,但这只是因为数据不够多,硬件不够支持。在资金足够的情况下,强人工智能已经…

WFPlayer

WFPlayer WFPlayer 可以实现分析音视频生成音频波形图 在线demo地址: demo WFPlayer支持: 在不加载整个媒体文件的情况下创建波形自定义光标、进度、网格、标尺显示和颜色加载媒体url和加载媒体dom元素(视频标签和音频标签)颜色或宽度等实时…

Linux 块设备操作函数

和字符设备的fil_operations一样,块设备也有操作集,为结构体block_device_operations,此结构体定义在include/linux/blkdev.h中,结构体内容如下: struct block_device_operations {int (*open) (struct block_device …

Flutter编译一直显示Running Gradle task ‘assembleDebug‘

🔥 目前开发的Android Studio版本 🔥 🔥 当前Flutter SDK 版本 🔥 Flutter 3.10.6 • channel stable • https://github.com/flutter/flutter.git Framework • revision f468f3366c (3 周前) • 2023-07-12 15:19:05 -0700 Eng…

MySQL之深入InnoDB存储引擎——Buffer Pool

文章目录 一、空闲链表的管理二、缓冲页的哈希处理三、Flush链表的管理四、LRU链表的管理五、脏页刷新六、多Buffer Pool实例 InnoDB存储引擎是基于磁盘存储的,并将其中的记录按照页的方式进行管理。在数据库系统中,由于CPU速度与磁盘速度之间的鸿沟&…

docker xserver是什么

在Docker环境中,XServer是一个用于图形显示的X Window系统服务器。X Window系统是一种常用的图形用户界面(GUI)系统,允许在图形化桌面环境中运行应用程序。 当在Docker容器中运行需要图形界面的应用程序时,通常需要将…

用户权限提升Sudo

目录 前言 一、su的用法 二、sudo提权 总结 前言 sudo是linux系统管理指令,是允许系统管理员让普通用户执行一些或者全部的root命令的一个工具,如halt,reboot,su等等。换句话说通过此命令可以让非root的用户运行只有root才有权限…

XML(eXtensible Markup Language)

目录 为什么需要XML? 一 XML语法 1.文档声明 2.元素 语法: 3.属性 4.注释 5.CDATA节 二 树结构 三 转义字符 四 DOM4J 1.XML解析技术 2.dom4j介绍 3.dom4j基本使用 XML 指可扩展标记语言(eXtensible Markup Language)。 XML 被设计用来传…

Killing LeetCode [83] 删除排序链表中的重复元素

Description 给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。 Intro Ref Link:https://leetcode.cn/problems/remove-duplicates-from-sorted-list/ Difficulty:Easy Tag&am…

全面讲解最小二乘法

常见的最小二乘法我们就不多说了,下面主要介绍一下最小二乘法的一些先进方法。 正则化的最小二乘法 在使用常见的最小二乘法进行回归分析时,常常会遇到过拟合的问题,也就是在训练数据集上表现的很好,但是在测试数据集上表现的很…

Python 实现语音转文本

Python 实现语音转文本 Python可以使用多种方式来实现语音转文本,下面介绍其中两种。 方法一:使用Google Speech API Google Speech API 是 Google 在 2012 年推出的一个 API,可以用于实现语音转文本。使用 Google Speech API 需要安装 Sp…

64位交叉编译器版本切换

操作系统版本 lkmaoubuntu:~$ cat /proc/version Linux version 5.6.18 (lkmaoubuntu) (gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)) #1 SMP Tue Jul 25 23:11:17 PDT 2023 lkmaoubuntu:~$ 64位 安装默认版本和gcc5版本。 sudo apt-get install gcc-aarch64-linux-g…

无涯教程-Perl - if...elsif...else语句函数

if 语句后可以跟可选的 elsif ... else 语句,这对于使用单个if ... elsif语句测试各种条件非常有用。 if...elsif...else - 语法 Perl编程语言中的 if ... elsif...else语句的语法是- if(boolean_expression 1) {# Executes when the boolean expression 1 is tr…

C语言案例 打印秋水仙花数-05

题目:打印出所有的水仙花数。 步骤一:定义程序目标 编写一个C程序,输出所有的水仙花数。步骤二:程序设计 原理:所谓“水仙花数”是指一个三位数,其各位数字立方和等于该数本身例如:153是一个“…

JavaScript 一段代码快速入门

仅记录了和c有所不同之处,其余类似。 一段简单代码 // 关注点分离,指html页面设计和javascript页面行为分离// 对象,键值对形式 const user {name: "gyf",age: 20,jobs: ["front-end", "engineer", 2, true…