算法——(树)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语言版本的代码实现,后续再补上。

猜你喜欢

转载自blog.csdn.net/weixin_44758107/article/details/127666551