算法——(树)BM41:输出二叉树的右视图

题目描述:
根据二叉树的前序、中序遍历,输出二叉树的右视图
例如:
前序:[1,2,4,5,3]
中序:[4,2,5,1,3]
则树应该为:二叉树
结果:[1,3,5]

今天看到这个题目很有意思,题目并不难但用到了不少算法知识,用到了3个面试常考算法:
1、根据前序、中序构建一棵树(中等)
2、树的前序遍历算法(简单)
3、DFS(深度优先搜索算法)按层遍历一棵树(中等)

swift:

/*
 buid tree + DFS按层按层遍历
 */
func solve ( _ xianxu: [Int],  _ zhongxu: [Int]) -> [Int] {
    var tmpPre = xianxu     //前序遍历数组
    var tmpMid = zhongxu    //中序遍历数组
    let buildResTree = buildTree(xianxu: &tmpPre, left1: 0, right1: tmpPre.count - 1, zhongxu: &tmpMid, left2: 0, right2: tmpMid.count - 1)     //递归的去建树
    var rowTraResArray = Array<Array<Int>>.init()
    rowTra(treeNode: buildResTree,resArr: &rowTraResArray,floor: 1)     //得到树 按层遍历的数组
    var result = Array<Int>.init()
    for floorArr in rowTraResArray {    //按层遍历的数组 每层的最后一个元素 就是右视图了
        result.append(floorArr.last!)
    }
    return result
}

/*
 根据前序数组、中序数组构建树
 xianxu : 前序遍历的数组
 left1  : 前序数组区间左
 right1 : 前序数组区间右
 zhongxu: 中序遍历的数组
 left2  : 中序数组区间左
 right2 : 中序数组区间右
 */
func buildTree (xianxu: inout [Int], left1: Int, right1: Int, zhongxu: inout [Int], left2: Int, right2: Int) -> TreeNode? {
    if(left1 > right1 || left2 > right2){   //因为后面需要这四个数字进行递归,一旦不合法就无法继续递归
        return nil
    }
    //找到 root 在 中序 的index
    var rootIndex = -1
    for i in left2...right2{
        if(xianxu[left1] == zhongxu[i]){
            rootIndex = i
            break
        }
    }
    /*
     本级递归需要做的事情
     1、构建本级TreeNode节点
     2、找到本级TreeNode节点的左右子树的 前序、中序数组,递归下去
     */
    let treeNode = TreeNode.init(xianxu[left1], nil, nil)
    let leftTreeSize = rootIndex - left2        //本级TreeNode节点 左子树大小
    let rightTreeSize = right2 - rootIndex      //本级TreeNode节点 右子树大小
    //下面的递归 是本算法最不容易理解的地方、认真思考、就会收获良多
    treeNode.left = buildTree(xianxu: &xianxu, left1: left1 + 1, right1: left1 + leftTreeSize, zhongxu: &zhongxu, left2: left2, right2: rootIndex - 1)
    treeNode.right = buildTree(xianxu: &xianxu, left1: right1 - rightTreeSize + 1, right1: right1, zhongxu: &zhongxu, left2: rootIndex + 1, right2: right2)
    return treeNode
}

/*
 根据树按层遍历,得到遍历数组
 */
func rowTra (treeNode: TreeNode?, resArr: inout [[Int]], floor: Int) {
    if(treeNode == nil){ return }
    if(resArr.count >= floor){      //该层还未遍历完毕、继续遍历
        resArr[floor - 1].append(treeNode!.val)
    }else{                          //需要新开一层
        var newArr = Array<Int>.init()
        newArr.append(treeNode!.val)
        resArr.append(newArr)
    }
    rowTra(treeNode: treeNode!.left, resArr: &resArr, floor: floor + 1)
    rowTra(treeNode: treeNode!.right, resArr: &resArr, floor: floor + 1)
}

时间复杂度:O(n),其中n为二叉树的节点数,二叉树共遍历两遍
空间复杂度:O(n),用到了数组存储按层遍历的节点值
如果朋友们需要C语言、Java语言版本的代码实现,后续再补上。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值