leetcode刷题(javaScript)——二叉树、平衡二叉树相关场景题总结

news2024/11/26 1:35:37

二叉树的知识点很多,在算法刷题中需要有想象力的数据结构了。主要是用链表存储,没有数组更容易理解。在刷二叉树相关算法时,需要注意以下几点:

  1. 掌握二叉树的基本概念:了解二叉树的基本概念,包括二叉树的定义、遍历方式(前序、中序、后序、层序遍历)、性质等。

  2. 熟练掌握二叉树的遍历算法:熟练掌握二叉树的前序、中序、后序遍历算法,以及它们的递归和迭代实现方式。

  3. 学习常见的二叉树算法题目:包括但不限于二叉树的最大深度、判断平衡二叉树、路径总和、对称二叉树等常见题目。

  4. 练习二叉树的递归和迭代实现:练习使用递归和迭代方式解决二叉树相关问题,加深对算法的理解和应用。

  5. 注意二叉树的性质和特点:了解二叉树的性质和特点,如完全二叉树、平衡二叉树、二叉搜索树等,可以更好地解决相关问题。

 简单介绍一下二叉树相关概念

 什么是二叉树

        二叉树是一种树形结构,每个节点最多有两个子节点(左子节点和右子节点)。根节点是位于树顶部的节点,叶子节点是没有子节点的节点。二叉树的每个节点最多有两个子节点,分别称为左子节点和右子节点。

 二叉树相关术语

  • 根节点:二叉树的顶部节点称为根节点。
  • 叶子节点:没有子节点的节点称为叶子节点。
  • 深度:从根节点到某个节点的唯一路径上的节点数称为该节点的深度。
  • 高度:从某个节点到叶子节点的最长路径上的节点数称为该节点的高度。
  • 子树:二叉树中每个节点都可以看作是根节点,它的左子树和右子树称为该节点的子树。

 二叉树的遍历方式

  • 前序遍历(Preorder Traversal):根节点 -> 左子树 -> 右子树
  • 中序遍历(Inorder Traversal):左子树 -> 根节点 -> 右子树
  • 后序遍历(Postorder Traversal):左子树 -> 右子树 -> 根节点
  • 层序遍历(Level Order Traversal):逐层从上到下,从左到右遍历节点

二叉树的分类

  • 满二叉树:每个节点要么没有子节点,要么有两个子节点。
  • 完全二叉树:除了最后一层外,每一层的节点都是满的,且最后一层的节点靠左排列。
  • 平衡二叉树:左右子树的高度差不超过1的二叉树。
  • 二叉搜索树(BST):左子树上所有节点的值均小于根节点的值,右子树上所有节点的值均大于根节点的值。

二叉树的表示方式

  • 链式存储结构:通过节点之间的引用关系来表示二叉树。
  • 顺序存储结构:使用数组来表示二叉树,按照层序遍历的顺序存储节点。

二叉树的常见操作

  • 插入节点:在二叉树中插入新节点,保持二叉树的结构特性。
  • 删除节点:从二叉树中删除指定节点,保持二叉树的结构特性。
  • 查找节点:在二叉树中查找指定值的节点。
  • 判断是否为平衡二叉树:判断二叉树的左右子树高度差是否小于等于1,从而判断是否为平衡二叉树。

二叉树递归技巧

  • 写出结束条件
  • 不要把树复杂化,就当做树是三个节点,根节点,左子节点,右子节点
  • 只考虑当前做什么,不用考虑下次应该做什么
  • 每次调用应该返回什么

 话不多说,上题目

144. 二叉树的前序遍历

给你二叉树的根节点 root ,返回它节点值的 前序 遍历。

 这里需要将遍历的结果存起来,需要定义一个数组。二叉树的遍历是一个递归的过程,考虑单独建一个函数,将arr作为入参传进去。对这个函数使用递归。最后返回arr。arr是一个引用类型,所以不需要函数返回值

/**
 * 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)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var preorderTraversal = function (root) {
    //定义数组存放遍历结果
    let arr = [];
    //将数组作为入参传进去
    preorder(root, arr);
    return arr;
};
function preorder(root, res) {
    if (root) {
        //前序遍历先存根节点
        res.push(root.val);
        //遍历左子树
        preorder(root.left, res);
        //遍历右子树
        preorder(root.right, res);
    }
}

 或者用数组的concat方法拼接遍历结果

/**
 * 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)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var preorderTraversal = function (root) {
    if(!root)return [];
    return [root.val].concat(preorderTraversal(root.left)).concat(preorderTraversal(root.right));
};

 栈的形式

思路:从根节点开始,入栈。栈存放未遍历的节点。入栈顺序是先后后左。则出栈是先左后右。根节点在第一次出栈时已确定位置,只用考虑左右子树的入栈顺序即可

var preorderTraversal = function (root) {
    if (!root) return [];
    let arr = [];
    let stack = [root];
    while (stack.length) {
        const o = stack.pop();
        //出栈的顺序是遍历的顺序
        arr.push(o.val);
        //入栈顺序先后后左
        o.right && stack.push(o.right);
        //左子树后入栈,下次pop时先处理
        o.left && stack.push(o.left);
    }
    return arr;
};

 94. 二叉树的中序遍历

给定一个二叉树的根节点 root ,返回 它的 中序 遍历

 思路:递归

先左,存根节点的val,在右

递归遍历时左右子树也会充当root,获取到val,所以只用考虑为空的时候

/**
 * 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)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var inorderTraversal = function (root) {
    if (!root) return [];
    return inorderTraversal(root.left).concat(root.val).concat(inorderTraversal(root.right));
};

思路:用栈实现

遇到根节点先push进栈,去找它的左子树,一直找到最后一个左子树

这个时候就找到中序遍历的第一个节点了,也就是放在栈顶元素,将其pop出来。然后去找右子树。同理,找右子树也先找其左孩子节点。如果右节点为空,继续栈顶pop,每次pop的都是未遍历的节点。

嗯。。。这里需要手动画个树思考一下

/**
 * 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)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var inorderTraversal = function (root) {
    if (!root) return [];
    const arr = [];
    const stack = [];
    let current = root;
    while (current || stack.length) {
        //每次遍历让current走到最左边
        while (current) {
            stack.push(current);
            current = current.left;
        }
        //最左边没有了话弹出当前处于最左边的叶子节点
        const o = stack.pop();
        arr.push(o.val);
        //弹出节点的右子树作为当前节点
        current = o.right;
    }
    return arr;
};

 注意:结束循环的条件是current没结束,或者栈里面还有没遍历的对象

 145. 二叉树的后序遍历

给你一棵二叉树的根节点 root ,返回其节点值的 后序遍历

思路:递归版本的后序遍历也是很简单的,利用数组的concat方法可以不用再新增数组进行存储。先遍历左子树,在右子树,最后是根节点,放val值。

/**
 * 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)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var postorderTraversal = function (root) {
    if (!root) return [];
    return postorderTraversal(root.left).concat(postorderTraversal(root.right)).concat(root.val);
};

 递归遍历相当于维护了一个隐藏的栈,如果用栈来暂存节点怎么实现?

 首先后序遍历,根节点是放在数组的最后一项,最先找到的是左子树最左边的节点。放入的顺序是【左右根左右根...根(root)】

查找节点的顺序是不是和前序遍历很像,只不过前序遍历先将根的val存起来,而后序遍历在左右子树查找完后再存。那如果换个角度思考,如果我遍历的时候遇到根节点将其放在未遍历节点的后面是不是就行了,其次是右节点放在未遍历前面,在然后是左节点放在未遍历前面。

/**
 * 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)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[]}
 */
var postorderTraversal = function (root) {
    if (!root) return [];
    let arr =[];//存放后序遍历的数组
    let stack =[root];
    //后序遍历入数组的顺序是左右根,按照前序遍历的思路入栈,但是存数组的时候从数组头部插入,而不是尾部
    while(stack.length){
        const o = stack.pop();
        arr.unshift(o.val);
        o.left && stack.push(o.left);
        o.right && stack.push(o.right);
    }
    return arr;
};

 push入栈的顺序是先左在右,这样在pop的时候右子树先出栈,进数组也是先进去。

这里arr用unshift方法每次在已遍历节点的头部插入当前遍历元素

100. 相同的树

给你两棵二叉树的根节点 pq ,编写一个函数来检验这两棵树是否相同。

如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。

 思路:相同位置挨个比较 ;失败的时候很好考虑,即如果p和q有一个先结束,一个还没结束,说明节点个数不同,返回false;如果p和q相同节点上元素值不同也会返回false。难点在于什么时候结束?

这里可以反向思考,全部比较完,p和q同时比较完没有在比较的元素的时候,即p=null q=null。能走到这步,说明前面p和q不为空时元素都相等,返回true。

/**
 * 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)
 * }
 */
/**
 * @param {TreeNode} p
 * @param {TreeNode} q
 * @return {boolean}
 */
var isSameTree = function (p, q) {
    //当前的p和q同时为空判断为相同
    if (!p && !q) return true;
    //如果两个树有一个缺失相应的节点,返回false
    if (!p || !q) return false;
    //如果两个节点都存在,但是值不相等,返回false
    if (p.val != q.val) return false;
    //递归p和q的左子树,以及p和q的右子树
    return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
};

 递归的思想只要将当前p和q整明白了,后面只是方法的递归调用罢了。

递归遍历p的left+q.left,拼接上递归调用p的right+q.right

101. 对称二叉树

给你一个二叉树的根节点 root , 检查它是否轴对称。

思路:跟上题类似,将数一分为二,左子树和右子树,比较左子树和右子树是否轴对称。

即左子树左节点==右子树右节点 && 左子树右节点==右子树左节点

什么情况下失败

  • 左右节点一个存在,一个为nul;
  • 左右节点同时存在,但val不相等。

什么情况下成功

左子树为右子树都为空,此时不需要递归,也就是叶子节点为true。

/**
 * 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)
 }
 */

/**
 * @param {TreeNode} root
 * @return {boolean}
 */
var isSymmetric = function (root) {
    return checkSymmetric(root.left, root.right);
};

function checkSymmetric(leftSubtree, rightSubtree) {
    // 如果左右子树都为null则对称
    if (!leftSubtree && !rightSubtree) return true;
    // 如果左右子树有一个缺失则非对称
    if (!leftSubtree || !rightSubtree) return false;
    // 节点都存在但值不同也返回false
    if (leftSubtree.val != rightSubtree.val) return false;
    // 否则左右子树都存在,继续递归判断左子树的左节点和右子树的右节点 以及左子树右节点和右子树左节点
    return checkSymmetric(leftSubtree.left, rightSubtree.right) && checkSymmetric(leftSubtree.right, rightSubtree.left);
}

 从根节点,一分为二,将左右子树看成是两个树进行对称比较。这里肯定是要创建一个函数来递归处理左右子树

104. 二叉树的最大深度

给定一个二叉树 root ,返回其最大深度。

二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。

这道题如果考虑到两层节点,就会复杂很多。比如将左右节点高度都考虑进去。这样提交没问题,直到看了题解,NM,1的情况可以合并在判空的时候处理。

/**
 * 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)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number}
 */
var maxDepth = function (root) {
    if (!root) return 0;
    if (!root.left && !root.right) return 1;
    if (root.left && root.right) {
        return 1 + Math.max(maxDepth(root.left), maxDepth(root.right));
    }
    if (root.left) return 1 + maxDepth(root.left);
    return 1 + maxDepth(root.right);
};

如下是简洁版本返回左子树和右子树中高度较高的那个+1,如果不存在返回0

简化版本再次印证了递归的的技巧:只考虑根左右三个节点的树!!!如果左子树或右子树有孩子进入下次递归就行了

/**
 * 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)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number}
 */
var maxDepth = function (root) {
    if (!root) return 0;
    return 1 + Math.max(maxDepth(root.left), maxDepth(root.right));
};

世界都清爽了。注意tips:尽量使用Math提供的方法,提示逼格,减少代码量

111. 二叉树的最小深度

给定一个二叉树,找出其最小深度。

最小深度是从根节点到最近叶子节点的最短路径上的节点数量。

说明:叶子节点是指没有子节点的节点。

思路:分析题目

  1. 如果同时存在左右子树,最小深度是左右子树的最小深度和+1
  2. 如果只存在左子树或右子树,最小深度等于左子树或右子树的深度+1
  3. 如果当前不为空,左右子树为空,返回1
  4. 如果是空则,返回0

其中2和3可以合并

/**
 * 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)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number}
 */
var minDepth = function (root) {
    if (!root) return 0;
    if (root.left && root.right) {
        return 1 + Math.min(minDepth(root.left), minDepth(root.right));
    }
    return 1 + minDepth(root.left || root.right);
};

226. 翻转二叉树

给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。

 思路:交换节点,根节点固定,交换左右

只用看示例2,只有三个节点的树。看下递归怎么解决

首先交换1和3,因为二叉树是指针串起来的,交换两个的地址指向就好了。

1变成3,需要先将3的信息暂存起来。

将暂存的3替换1

根节点交换完成,在递归处理根的左子树,右子树。

在递归处理,也就是第二次处理时,左子树的节点充当root,右子树的节点也会充当root

/**
 * 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)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {TreeNode}
 */
var invertTree = function (root) {
    if (!root) return null;
    let temp = root.left;
    root.left = root.right;
    root.right = temp;
    invertTree(root.left);
    invertTree(root.right);
    return root;
};

110. 平衡二叉树

给定一个二叉树,判断它是否是高度平衡的二叉树。

本题中,一棵高度平衡二叉树定义为:

一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。

 

思路:注意解题,题目说的每个节点的左右子树高度差不能超过1

继续利用递归处理。简单来说,先创建一个方法用于计算某个子树的高度。在将根节点的左右子树高度进行计算,如果根节点的左右子树高度差大于1则返回false。(只考虑根节点能通过90%的用例)

最后要判断,左右子树是否也满足高度相差1。像下面的示例,虽然根节点满足了,但是下面的2的左右高度差为2不满足。

/**
 * 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)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {boolean}
 */
var isBalanced = function (root) {
    if (!root) return true;
    if( Math.abs(getHeight(root.left) - getHeight(root.right)) > 1){
        return false;
    }
    return isBalanced(root.left) && isBalanced(root.right);
};
function getHeight(node) {
    if (!node) return 0;
    return 1 + Math.max(getHeight(node.left), getHeight(node.right));
}

222. 完全二叉树的节点个数

给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。

完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。

 思路:这道题最笨的方法可能是递归找所有的节点,统计个数。

然而要利用这道题的结构,完全二叉树,我们在学习数据结构的时候,完全二叉树有个特性,就是高度如果为h,那么h-1层一定铺满,或者说h-1层一定是满二叉树。

这道题求节点总数,如果按层来看,不好处理。

换个角度,从中间砍一刀,一分为二,左右子树。

可以发现,完全二叉树就分两种

  • 一种是左子树第h层铺满,但右子树没铺满
  • 另一种是左子树h层有节点,而右子树h层没有

为什么这么看呢?

两种情况分别可以确定左子树的个数、右子树的个数

对于未确定的右子树或左子树可以采用递归方式处理

/**
 * 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)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number}
 */
var countNodes = function (root) {
    if (!root) return 0;
    let leftHeight = getHeight(root.left);
    let rightHeight = getHeight(root.right);
    //左右高度相等,左子树是满二叉树,个数=2^高度-1  别忘了根节点+1
    if (leftHeight == rightHeight) {
        return Math.pow(2, leftHeight) + countNodes(root.right);
    }
    //左子树大于右子树,右子树是满二叉树,个数=2^右子树的高度-1 加上根节点+1
    return Math.pow(2, rightHeight) + countNodes(root.left);
};
function getHeight(node) {
    if (!node) return 0;
    return 1 + Math.max(getHeight(node.left), getHeight(node.right));
}

257. 二叉树的所有路径

给你一个二叉树的根节点 root ,按 任意顺序 ,返回所有从根节点到叶子节点的路径。

叶子节点 是指没有子节点的节点。

思路:使用深度优先搜索(DFS)算法来遍历二叉树,并在遍历的过程中记录从根节点到叶子节点的路径。深度搜索递归结束条件是找到叶子节点,将路径信息打印到result中。

/**
 * 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)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {string[]}
 */
var binaryTreePaths = function (root) {
    if (!root) return [];
    let result = [];
    dfs(root, [], result);
    return result;
};
//深度遍历递归方式,携带路径信息,result结果信息
function dfs(root, path, result) {
    if (!root) return;
    path.push(root.val);
    if (!root.left && !root.right) {
        //碰到叶子节点结束递归
        result.push(path.join('->'));
    } else {
        //进行递归,将当前路径信息带入,注意浅拷贝当前路径信息
        dfs(root.left, path.slice(), result);
        dfs(root.right, path.slice(), result);
    }
}

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

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

相关文章

pytorch什么是梯度

目录 1.导数、偏微分、梯度1.1 导数1.2 偏微分1.3 梯度 2. 通过梯度求极小值3. learning rate 1.导数、偏微分、梯度 1.1 导数 对于yx 2 2 2 的导数,描述了y随x值变化的一个变化趋势,导数是个标量反应的是变化的程度,标量的长度反应变化率的…

next/future/image图片根据外部容器100%填充

官网文档地址&#xff1a; https://nextjs.org/docs/pages/api-reference/components/image 主要需要使用属性fill。外部元素需要设置好position:relative <Imagexsrc"/images/1.jpg"fillsizes100vw />

浅谈块存储、文件存储、对象存储

**块存储、文件存储和对象存储各自有其独特的特点和适用场景**。具体来说&#xff1a; 1. **块存储**&#xff1a; - 描述&#xff1a;块存储将存储空间分割成固定大小的块&#xff0c;这些块可以直接映射到主机操作系统。它提供的是原始的存储空间&#xff0c;不带文件系统…

hive实战项目:旅游集市数仓建设

旅游集市数仓建设 文章目录 旅游集市数仓建设为什么要设计数据分层&#xff1f;分层设计ODS&#xff08;Operational Data Store&#xff09;&#xff1a;数据运营层DW&#xff08;Data Warehouse&#xff09;&#xff1a;数据仓库层DWD&#xff08;Data Warehouse Detail&…

软考63-上午题-【面向对象技术】-面向对象的基本概念2

一、动态绑定、静态绑定 1-1、动态绑定、静态绑定的定义 编译时进行的绑定 静态绑定 运行时进行的绑定 动态绑定 动态绑定&#xff0c;和类的继承和多态想关联的。 在运行过程中&#xff0c;当一个对象发送消息请求服务时&#xff0c;要根据接受对象的具体情况将请求的操作…

gitlab的安装

1、下载rpm 安装包 (1)直接命令下载 wget https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/gitlab-ce-11.6.10-ce.0.el7.x86_64.rpm&#xff08;2&#xff09;直接去服务器上下载包 Index of /gitlab-ce/yum/el7/ | 清华大学开源软件镜像站 | Tsinghua Open Source…

html标签之列表标签,含爱奇艺,小米,腾讯,阿里

什么是css块元素&#xff1f; 块级元素是独占一行显示的。它的兄弟元素必定不会与其在同一行中&#xff08;除非脱离了文档流&#xff09;。通俗点来说&#xff0c;就是块元素(block element)一般是其他元素的容器元素&#xff0c;能容纳其他块元素或内联元素。 css块元素的三…

Mol2文件处理-拆分、合并、提取名称、计数与格式转换

欢迎浏览我的CSND博客&#xff01; Blockbuater_drug …点击进入 文章目录 前言一、Mol2文件合并二、Mol2文件拆分为含有单个分子的文件三、Mol2文件分子名称修改与提取3.1 分子名称修改去除空格3.2 文件名称提取 四、Mol2文件包含分子计数4.1 Mol2文件中分子计数4.2 分子计数传…

容器化软件应用简化传统设备的连接

| Docker容器如何简化工业物联网解决方案 制造和包装工厂可通过集成IT和OT技术来改善运营&#xff0c;从而释放预测性维护、数据分析以及接入强大的企业管理应用等优势。然而&#xff0c;对于缺乏员工、时间或资源的企业而言&#xff0c;实施工业物联网解决方案并不容易。对此…

Nircmd集成定时执行专家之后的使用场景

Nircmd工具拥有了定时执行功能之后&#xff0c;可以用于以下场景&#xff1a; 1. 自动化日常工作 定时清理系统垃圾文件定时备份重要文件定时关闭或重启电脑定时发送邮件或短信定时执行其他程序或脚本 2. 监控系统状态 定时检查系统温度定时检查磁盘空间定时检查网络连接定时…

浏览器工作原理与Javascript高级(异步)

总体介绍 浏览器运行是多进程的&#xff0c;包括主进程、渲染进行、网络进程和GPU进程等等 解析HTML时(渲染进程)用到两大引擎&#xff0c;一个是渲染引擎&#xff08;用于渲染页面&#xff09;、一个是JS引擎用于解析JS代码。又JS引擎运行是单线程的&#xff0c;所以渲染和 …

【LeetCode:98. 验证二叉搜索树 + 递归】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

消息队列-kafka-服务端处理架构(架构,Topic文件结构,服务端数据的一致性)

服务端处理架构 资料来源于网络 网络线程池&#xff1a; 接受请求&#xff0c;num.network.threads&#xff0c;默认为 3&#xff0c;专门处理客户的发送的请求。 IO 线程池&#xff1a; num.io.threads&#xff0c;默认为 8&#xff0c;专门处理业务请求。也就是它不负责发…

CSS盒模型居中方法,web开发问题

CSS 篇 link 与 import 的区别 link 是 HTML 方式&#xff0c; import 是CSS方式link 最大限度支持并行下载&#xff0c; import 过多嵌套导致串行下载&#xff0c;出现 FOUC (文档样式短暂失效)link 可以通过 rel"alternate stylesheet" 指定候选样式浏览器对 lin…

数据结构学习(四)高级数据结构

高级数据结构 1. 概念 之所以称它们为高级的数据结构&#xff0c;是因为它们的实现要比那些常用的数据结构要复杂很多&#xff0c;能够让我们在处理复杂问题的过程中&#xff0c; 多拥有一把利器&#xff0c;同时掌握好它们的性质&#xff0c;以及所适应的场合&#xff0c;在…

第十篇:如何利用人工智能技术做好营销流量整形管理?(Traffic Shaping)- 我为什么要翻译介绍美国人工智能科技巨头IAB公司

IAB平台&#xff0c;使命和功能 IAB成立于1996年&#xff0c;总部位于纽约市​​​​​​​。 作为美国的人工智能科技巨头社会媒体和营销专业平台公司&#xff0c;互动广告局&#xff08;IAB- the Interactive Advertising Bureau&#xff09;自1996年成立以来&#xff0c;先…

基于springboot+vue实现食品安全管理系统项目【项目源码+论文说明】

基于springboot实现食品安全管理系统演示 摘要 食品行业同其他行业有很多的差别&#xff0c;食品行业不仅要管食品的生产和销售&#xff0c;还要管食品的库存和保质期&#xff0c;那么对于食品管理者来说&#xff0c;就存在着一定的难度。况且食品的种类复杂&#xff0c;存储条…

ZWT_各向同性线弹性材料本构模型umat的应用

线弹性材料本构模型 对于多数材料而言&#xff0c;在微小变形的假设下&#xff0c;会满足线弹性理论&#xff0c;数学可以表示为&#xff1a; σ i j C i j k l ε k l E 1 ν ( ε i j ν 1 − 2 ν ε k k δ i j ) \begin{align*} \sigma_{ij}&C_{ijkl}\varepsilon…

风丘道路载荷数据采集(RLDA)测试方案

一 背景 整车厂在汽车上市前&#xff0c;了解产品所能承受的载荷是非常重要的&#xff0c;因此需进行道路载荷数据采集&#xff08;RLDA&#xff09;测试。通过获得车辆在实际试验场或公路道路中行驶的载荷信息来为整车台架道路模拟试验提供目标信号输入&#xff0c;以及为用于…

android高级面试题及答案,已拿offer

一、java相关 java基础 1、java 中和 equals 和 hashCode 的区别 2、int、char、long 各占多少字节数 3、int 与 integer 的区别 4、谈谈对 java 多态的理解 5、String、StringBuffer、StringBuilder 区别 6、什么是内部类&#xff1f;内部类的作用 7、抽象类和接口区别 java高…