牛客面试高频算法题js(输出二叉树的右视图、岛屿数量、矩阵的最小路径和、字符串出现次数的TopK问题、二叉树根节点到叶子节点的所有路径和)

2023-11-01

NC136 输出二叉树的右视图

描述

请根据二叉树的前序遍历,中序遍历恢复二叉树,并打印出二叉树的右视图

数据范围: 0 \le n \le 100000≤n≤10000
要求: 空间复杂度 O(n)O(n),时间复杂度 O(n)O(n)

如输入[1,2,4,5,3],[4,2,5,1,3]时,通过前序遍历的结果[1,2,4,5,3]和中序遍历的结果[4,2,5,1,3]可重建出以下二叉树:

在这里插入图片描述

所以对应的输出为[1,3,5]。

示例1

输入:

[1,2,4,5,3],[4,2,5,1,3]

返回值:

[1,3,5]

备注:

二叉树每个节点的值在区间[1,10000]内,且保证每个节点的值互不相同。
/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 * 求二叉树的右视图
 * @param xianxu int整型一维数组 先序遍历
 * @param zhongxu int整型一维数组 中序遍历
 * @return int整型一维数组
 */

function solve( xianxu ,  zhongxu ) {
//    利用前序遍历和中序遍历的数组创建树(递归)
    function buildTree(xianxu,zhongxu ){
        if(xianxu.length==0||zhongxu.length==0){
            return null;
        }
        let tree={
            val:xianxu[0],
            left:null,
            right:null,
        }
//         寻找中序遍历中的跟节点
        let index=zhongxu.indexOf(xianxu[0]);
//         递归构建左右子树
        tree.left=buildTree(xianxu.slice(1,index+1),zhongxu.slice(0,index));
        tree.right=buildTree(xianxu.slice(index+1,xianxu.length),zhongxu.slice(index+1,zhongxu.length))
        return tree;
    }
    
    let tree=buildTree(xianxu,zhongxu);
    let res=[];
    let p=[];
    let x=[];
    p.push(tree);
//     res.push(tree.val)
//     层序遍历,每次循环p中最后一个节点为每层树最右边的节点
    while(p.length!=0){
        let len=p.length;
        for(let i=0;i<len;i++){
            let node = p.shift();
//             当i循环至最后,将节点值推入数组中
            if(i==len-1)
                res.push(node.val);
            if(node.left){
                p.push(node.left);
            }
            if(node.right){
                p.push(node.right);
             
            }
        }
    }
    return res;
    
    
}
module.exports = {
    solve : solve
};

NC109 岛屿数量

描述

给一个01矩阵,1代表是陆地,0代表海洋, 如果两个1相邻,那么这两个1属于同一个岛。我们只考虑上下左右为相邻。

岛屿: 相邻陆地可以组成一个岛屿(相邻:上下左右) 判断岛屿个数。

例如:

输入

[

[1,1,0,0,0],

[0,1,0,1,1],

[0,0,0,1,1],

[0,0,0,0,0],

[0,0,1,1,1]

]

对应的输出为3

(注:存储的01数据其实是字符’0’,‘1’)

示例1

输入:

[[1,1,0,0,0],[0,1,0,1,1],[0,0,0,1,1],[0,0,0,0,0],[0,0,1,1,1]]

返回值:

3

示例2

输入:

[[0]]

返回值:

0

示例3

输入:

[[1,1],[1,1]]

返回值:

1

备注:

01矩阵范围<=200*200

思路:
深度优先搜索(dfs) 深度优先搜索一般用于树或者图的遍历,其他有分支的(如二维矩阵)也适用。它的原理是从初始点开始,一直沿着同一个分支遍历,直到该分支结束,然后回溯到上一级继续沿着一个分支走到底,如此往复,直到所有的节点都有被访问到。
step 1:优先判断空矩阵等情况。
step 2:从上到下从左到右遍历矩阵每一个位置的元素,如果该元素值为1,统计岛屿数量。
step 3:接着将该位置的1改为0,然后使用dfs判断四个方向是否为1,分别进入4个分支继续修改。
在这里插入图片描述

代码:

/**
 * 判断岛屿数量
 * @param grid string字符串型二维数组 
 * @return int整型
 */
function solve( grid ) {
     let n=grid.length;
    let m=grid[0].length;
//     递归节点并置0,当该节点四周有节点为1,则继续递归
    function dfs(grid,i,j){
       
        grid[i][j]="0";
//         左
        if(i-1>=0&&grid[i-1][j]=="1"){
            dfs(grid,i-1,j)
        }
//         上
        if(j-1>=0&&grid[i][j-1]=="1"){
            dfs(grid,i,j-1)
        }
//         右
        if(i+1<n&&grid[i+1][j]=="1"){
              dfs(grid,i+1,j)
        }
//         下
        if(j+1<m&&grid[i][j+1]=="1"){
            dfs(grid,i,j+1)
        }
    }
    let count=0;
    for(let i=0;i<n;i++){
        for(let j=0;j<m;j++){
//             遍历每一个节点
            if(grid[i][j]=="1"){
                count++;
                dfs(grid,i,j);
            }
        }
    }
    
    
    return count;
}
module.exports = {
    solve : solve
};

NC59 矩阵的最小路径和

描述

给定一个 n * m 的矩阵 a,从左上角开始每次只能向右或者向下走,最后到达右下角的位置,路径上所有的数字累加起来就是路径和,输出所有的路径中最小的路径和。

数据范围: 1 \le n,m\le 5001≤n,m≤500,矩阵中任意值都满足 0 \le a_{i,j} \le 1000≤a**i,j≤100

要求:时间复杂度 O(nm)O(n**m)

例如:当输入[[1,3,5,9],[8,1,3,4],[5,0,6,1],[8,8,4,0]]时,对应的返回值为12,

所选择的最小累加和路径如下图所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Sq9qGSsM-1658923862407)(https://uploadfiles.nowcoder.com/images/20220122/423483716_1642823916509/06EB123C153852AF55ED51448BEAD1BA)]

示例1

输入:

[[1,3,5,9],[8,1,3,4],[5,0,6,1],[8,8,4,0]]

返回值:

12

示例2

输入:

[[1,2,3],[1,2,3]]

返回值:

7

思路:
step 1:我们可以构造一个与矩阵同样大小的二维辅助数组,其中dp[i][j]dp[i][j]dp[i][j]表示以(i,j)(i,j)(i,j)位置为终点的最短路径和,则dp[0][0]=matrix[0][0]dp[0][0] = matrix[0][0]dp[0][0]=matrix[0][0]。
step 2:很容易知道第一行与第一列,只能分别向右或向下,没有第二种选择,因此第一行只能由其左边的累加,第一列只能由其上面的累加。
step 3:边缘状态构造好以后,遍历矩阵,补全矩阵中每个位置的dp数组值:如果当前的位置是(i,j)(i,j)(i,j),上一步要么是(i−1,j)(i-1,j)(i−1,j)往下,要么就是(i,j−1)(i,j-1)(i,j−1)往右,那么取其中较小值与当前位置的值相加就是到当前位置的最小路径和,因此状态转移公式为dp[i][j]=min(dp[i−1][j],dp[i][j−1])+matrix[i][j]dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + matrix[i][j]dp[i][j]=min(dp[i−1][j],dp[i][j−1])+matrix[i][j]。
step 4:最后移动到(n−1,m−1)(n-1,m-1)(n−1,m−1)的位置就是到右下角的最短路径和。

在这里插入图片描述

代码:

/**
 * 
 * @param matrix int整型二维数组 the matrix
 * @return int整型
 */
function minPathSum( matrix ) {
    let n=matrix.length;
    let m=matrix[0].length;
//     dp[i][j]表示以当前i,j位置为终点的最短路径长
    let dp=new Array(n+1);
    for(let i=0;i<dp.length;i++){
        dp[i]=new Array(m+1)
    }
//     第一列数据只能向右走,所以即为当前位置加上前一个位置
    dp[0][0]=matrix[0][0];
    for(let i=1;i<n;i++){
        dp[i][0]=dp[i-1][0]+matrix[i][0];
    }
//     第一行数据只能向下走,所以即为当前位置加上前一个位置
    for(let j=1;j<m;j++){
        dp[0][j]=dp[0][j-1]+matrix[0][j];
    }
//     每个方块只能向下或者向右走,所以遍历到当前位置时,选择
//     上方和左方最小的数据与当前位置相加,遍历至矩阵最后一个即为答案
    
    for(let i=1;i<n;i++){
        for(let j=1;j<m;j++){
            dp[i][j]=Math.min(dp[i-1][j],dp[i][j-1])+matrix[i][j];
        }
    }
    return dp[n-1][m-1];
}
module.exports = {
    minPathSum : minPathSum
};

NC97 字符串出现次数的TopK问题

描述

给定一个字符串数组,再给定整数 k ,请返回出现次数前k名的字符串和对应的次数。

返回的答案应该按字符串出现频率由高到低排序。如果不同的字符串有相同出现频率,按字典序排序。

对于两个字符串,大小关系取决于两个字符串从左到右第一个不同字符的 ASCII 值的大小关系。

比如"ah1x"小于"ahb",“231”<”32“

字符仅包含数字和字母

数据范围:字符串数满足 0 \le n \le 1000000≤n≤100000,每个字符串长度 0 \le n \le 100≤n≤10,0 \le k \le 25000≤k≤2500

要求:空间复杂度 O(n)O(n),时间复杂度O(n \log k)O(nlogk)

示例1

输入:

["a","b","c","b"],2

返回值:

[["b","2"],["a","1"]]

说明:

"b"出现了2次,记["b","2"],"a"与"c"各出现1次,但是a字典序在c前面,记["a","1"],最后返回[["b","2"],["a","1"]]
   

示例2

输入:

["123","123","231","32"],2

返回值:

[["123","2"],["231","1"]]

说明:

 "123"出现了2次,记["123","2"],"231"与"32"各出现1次,但是"231"字典序在"32"前面,记["231","1"],最后返回[["123","2"],["231","1"]]   

示例3

输入:

["abcd","abcd","abcd","pwb2","abcd","pwb2","p12"],3

返回值:

[["abcd","4"],["pwb2","2"],["p12","1"]]

备注:

1 \leq N \leq 10^51≤N≤105
/**
 * return topK string
 * @param strings string字符串一维数组 strings
 * @param k int整型 the k
 * @return string字符串二维数组
 */
function topKstrings( strings ,  k ) {
    let map=new Map();
//    先让strings数组中的字符按ASCII排序
    strings.sort();
    
    for(let i=0;i<strings.length;i++){
//         判断map中是否存在为该字符组的键
        if(map.has(strings[i])){
//             如果存在则将字符去除并加1后存入map中
//             let x=Number(map.get(strings[i]))+1;
             let x=map.get(strings[i])+1
            map.set(strings[i],x);
        }else{
//             如果不存在 ,则以字符为键值为1存入map中
            map.set(strings[i],1);
        }
    }
//     将map中的数据转换成二维数组
    let arr=Array.from(map);
//     以二维中的第二列进行排序
    arr.sort((a,b)=>b[1]-a[1]);
    
   return arr.slice(0,k);
}
module.exports = {
    topKstrings : topKstrings
};

NC5 二叉树根节点到叶子节点的所有路径和

描述

给定一个二叉树的根节点root,该树的节点值都在数字\ 0-9 0−9 之间,每一条从根节点到叶子节点的路径都可以用一个数字表示。

1.该题路径定义为从树的根结点开始往下一直到叶子结点所经过的结点
2.叶子节点是指没有子节点的节点
3.路径只能从父节点到子节点,不能从子节点到父节点
4.总节点数目为n

例如根节点到叶子节点的一条路径是1\to 2\to 31→2→3,那么这条路径就用\ 123 123 来代替。
找出根节点到叶子节点的所有路径表示的数字之和
例如:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4sxebUxt-1659008704416)(https://uploadfiles.nowcoder.com/images/20200807/999991351_1596786228797_BC85E8592A231E74E5338EBA1CFB2D20)]

这颗二叉树一共有两条路径,
根节点到叶子节点的路径 1\to 21→2 用数字\ 12 12 代替
根节点到叶子节点的路径 1\to 31→3 用数字\ 13 13 代替
所以答案为\ 12+13=25 12+13=25

数据范围:节点数 0 \le n \le 1000≤n≤100,保证结果在32位整型范围内

要求:空间复杂度 O(n)O(n),时间复杂度 O(n^2)O(n2)

进阶:空间复杂度 O(n)O(n),时间复杂度 O(n)O(n)

示例1

输入:

{1,2,3}

返回值:

25

示例2

输入:

{1,0}

返回值:

10

示例3

输入:

{1,2,0,3,4}

返回值:

257

思路:

方法一(dfs):

/*
 * function TreeNode(x) {
 *   this.val = x;
 *   this.left = null;
 *   this.right = null;
 * }
 */

/**
  * 
  * @param root TreeNode类 
  * @return int整型
  */
function sumNumbers( root ) {
    // 方法一(dfs)

    function dfs(root,pretotal){
//         当树为空时返回0
       if(root==null){
           return 0
       }
//         total为当前节点值加上上一个节点的值
       let  total=pretotal*10+root.val;
//         如果当前节点为跟节点则返回total
         if(root.left==null&&root.right==null){
            return total;
//              如果不为跟节点则深度搜素左子树加右子树
        }else{
            return dfs(root.left,total)+dfs(root.right,total);
        }
        
    }
    
    return dfs(root,0);

}
module.exports = {
    sumNumbers : sumNumbers
};

思路:
1、初始时,将根节点和根节点的值分别加入两个队列。每次从两个队列分别取出一个节点和一个数字,进行如下操作:
如果当前节点是叶子节点,则将该节点对应的数字加到路径之和;
如果当前节点不是叶子节点,则获得当前节点的非空子节点,并根据当前节点对应的数字和子节点的值计算子节点对应的数字,然后将子节点和子节点对应的数字分别加入两个队列。
2、搜索结束后,即可得到所有叶子节点对应的路径之和。
在这里插入图片描述

方法二(bfs):

//    方法二(bfs)
//     如果树为空返回0
    if(root==null){
        return 0;
    }
//    p用来存储每层的节点
    let p=[];
//     结果和
    let sum=0;

    p.push(root);
//     num用来存储每层接节点的路径和
    let num=[root.val];
    while(p.length!=0){
        let len=p.length;
        for(let i=0;i<len;i++){
            
            let node=p.shift();
//             弹出上层路径和
            let n=num.shift();
//             如果当前节点为叶节点
            if(node.left==null&&node.right==null){
//                 结果和加上当前的n
                sum+=n;
//                 num.shift()
            }
//             如果当前节点有左子树
            if(node.left){
//                 将节点推入p中
                p.push(node.left);
//                 将当前n乘上10在加上左节点的值
                num.push(n*10+node.left.val)
            } 
//             同上
            if(node.right){
                p.push(node.right);
                 num.push(n*10+node.right.val)
            }
        }
    }
    
    return sum;
}
module.exports = {
    sumNumbers : sumNumbers
};
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

牛客面试高频算法题js(输出二叉树的右视图、岛屿数量、矩阵的最小路径和、字符串出现次数的TopK问题、二叉树根节点到叶子节点的所有路径和) 的相关文章

随机推荐

  • Linux系统下word转pdf,xls转pdf,ppt转pdf

    word转换pdf的技术方案 供参考 doc docx ppt pptx xls xlsx均支持转换 本方案是Java结合shell命令完成 不同于以往的仅依赖java组件转换或打印pdf的方案 需要目标服务器安装office套件 可选方案
  • LayUI登录页面

    使用LayUI对你所做系统进行前端的美化和交互完善设计 使得系统的操作和交互更加符合人机交互理念 下面文章仅是登录页面的美化
  • 国际期货是什么?正大期货的定义怎么来的?

    国际期货市场是国际上进行期货交易的市场 期货交易是预先签订商品买卖合同 而贷款的支付和货物的交割要在约定的时间内进行的一种交易 但一般不需要真正交割 绝大多数合约在到期前对冲 期货交易只需支付少量保证金 通过期货交易所买进卖出期货合约 即一
  • Anaconda配置OpenCV环境

    1 移除旧的环境 如果原来有一个opencv的环境 那么要先进行这个环境的删除 conda env remove opencv 2 虚拟环境创建 首先进行虚拟环境的创建 使用Anaconda进行虚拟环境的创建 我这里的虚拟环境的名称是 op
  • Java如何让自定义类型具有可比较大小的能力

    自定义类型大小比较 一 背景 二 两种方法 方式一 自然排序 方式二 定制排序 一 背景 Java中基本数据类型之间可以使用比较运算符 gt lt gt lt 等进行比较 引用数据类型之间进行比较时 使用继承于Object类的equals方
  • atheros面试

    6道题目 1 是swap的宏的定义 2 用一个语句判断一个数是不是2的n次幂 3 判断sizeof作为参数传入的 char 的长度 4 用两个栈实现一个队列 5 将字符串bcde转换为edcb 6 循环计数1 n 如果计到m 则打印出来 第
  • Impala 三大组件:Impala Daemon, Impala Statestore, Impala Catelog

    Impala 三大组件 Impala Daemon 功能 负责读写数据文件 接受来自 Impala shell ODBC Hue 和 JDBC 的查询请求 然后与集群中的其他节点分布式并行工作 将本节点的查询结果返回给中心协调者节点 查询流
  • 创建项目Vue 3 + Vite,引入 Element Plus UI 组件库。

    首先要下载vite 在终端输入npm init vitejs app my vue app template vue 快速生成一个使用 Vite 构建的 Vue 3 项目模版 这时候如果是第一次创建 电脑就会提示 只用输入y 电脑即可自动下
  • 高通9008刷机

    1 进入9008模式 第一种方法 adb reboot edl 第二种方法 手机按钮进入 第三种方法 小米安全通线 第四种方法 短路接点 2 需要安装安卓驱动 高通驱动 QFIL软件 3 需要下载ROM包 4 解压ROM包 5 打开QFIL
  • 毕业季

    进入六月 毕业的氛围越来越浓 虽然忙 但更多的是不舍 四年 转眼之间 大一在高密校区的岁月仍历历在目 6 10 从公司请假 早上八点半去图书馆布置创新比赛的展板 6 11 休整一天 PPT准备6 12号早上的答辩 6 12 早八点半 在中德
  • 欧科云链让科技赋能乡村教育,获公益时报等主流媒体报道...

    中国经济网 公益时报前线报道 近日 欧科云链CSR团队到访饶河县饶河农场中心小学 为该校的人工智能创客实验室注入了新的活力 这一举措旨在助力学校推进人工智能教育 为农村学生提供更广阔的发展机会 饶河农场中心小学一直以来致力于创新教育 自20
  • nested exception is org.apache.ibatis.builder.BuilderException: Error evaluating expression 的解决办法

    问题概述 在基于微服务架构风格的项目开发过程中 为了提高快速开发的目的 提高开发效率 集成了 MyBatisPlus 对于 MyBatisPlus 封装的 CRUD API 接口已经非常强大了 但是有时还是需要使用其动态 SQL 的拼接 在
  • 性能测试之性能优化篇

    目录 为什么进行性能测试 性能测试的目的 服务性能优化的思考 衡量系统性能常用的指标 系统性能计数器 性能测试分类 如何合理的规划我们的架构性能 最后拿数据说话 性能优化原则 性能优化的方法 性能优化的分层思想 所有的优化都会对系统性能产生
  • flask 文件 服务器,flask服务器文件上传云

    flask服务器文件上传云 内容精选 换一换 弹性云服务器支持通过内网访问OBS OBS可供用户存储任意类型的数据 将图片 视频等数据存储至OBS后 在ECS上可以访问OBS 下载桶中的图片或视频等数据 通过内网访问OBS 可以避免因网络不
  • ASP.NET中JSON的序列化和反序列化

    在项目开发过程中 发现需要用到JSON序列化 反序列化的问题 所有 在网上找到了一下这篇文章 摘录了下来 摘自 http www cnblogs com zhaozhan archive 2011 01 09 1931340 html JS
  • 使用ijkplayer播放4k视频卡顿的解决方法

    使用ijkplayer播放4k视频卡顿的解决方法 使用硬解码 ijkMediaPlayer setOption IjkMediaPlayer OPT CATEGORY PLAYER mediacodec 1
  • PAT甲级1135

    红黑树的特点 1 根节点是黑色 2 如果一个节点是红色那么他的两个子节点都是红色 3 任意从根节点到叶子结点的路径上 所有的路径经过的黑色节点数相同 4 红黑树是二叉搜索树 算法 1 根节点是否为黑色 2 红色节点的两个子节点是不是都是黑色
  • JS 数组或对象的遍历(for、for...in、for...of、foreach)

    转载自 JavaScript 比较for for in for of forEach的区别 非早起选手的博客 CSDN博客 目录 一 for 二 for in 三 for of 四 forEach 五 小结 一 for 最原始的方法 用来遍
  • 【在线教育】- 前端环境搭建&讲师CURD前端实现

    在线教育 一 在线教育前端环境搭建 1 1 vue element admin 概述 1 2 vue element admin master安装 1 3 vue element template介绍 了解 1 4 vue element
  • 牛客面试高频算法题js(输出二叉树的右视图、岛屿数量、矩阵的最小路径和、字符串出现次数的TopK问题、二叉树根节点到叶子节点的所有路径和)

    NC136 输出二叉树的右视图 描述 请根据二叉树的前序遍历 中序遍历恢复二叉树 并打印出二叉树的右视图 数据范围 0 le n le 100000 n 10000 要求 空间复杂度 O n O n 时间复杂度 O n O n 如输入 1