Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/95.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 在Swift中计算树的平均级别时如何跳过nil值_Ios_Swift - Fatal编程技术网

Ios 在Swift中计算树的平均级别时如何跳过nil值

Ios 在Swift中计算树的平均级别时如何跳过nil值,ios,swift,Ios,Swift,我已经使用Swift实现了以下功能。它计算树的每一级的平均值。只要节点的值不包含nils,它就可以正常工作 失败 基本上,这个测试用例是失败的:[10,5,15,null,null,6,20] 要将其可视化,树仍将如下所示: 10 5 15 6 20 基本上跳过零。 我的输出是:[10.0,10.0]当它应该是[10.0,10.0,13.0] 传球 它通过了这个测试用例:[3,9,20,15,7] 输出正确[3.0,14.5,

我已经使用Swift实现了以下功能。它计算树的每一级的平均值。只要节点的值不包含nils,它就可以正常工作

失败

基本上,这个测试用例是失败的:
[10,5,15,null,null,6,20]

要将其可视化,树仍将如下所示:

       10

   5         15

          6     20
基本上跳过零。 我的输出是:
[10.0,10.0]
当它应该是
[10.0,10.0,13.0]

传球

它通过了这个测试用例:
[3,9,20,15,7]
输出正确
[3.0,14.5,11.0]

形象化为

       3

   9        20

         15     7
实施

func averageOfLevels(_ root: TreeNode?) -> [Double] {
        var avg = [Double]()
        var queue = [TreeNode?]()//an array that will be treated as a queue

        queue.append(root)

        while(!queue.isEmpty) { //while there is at least one discovered node
            let current: TreeNode! = queue.first!

            var levelSum = 0.0
            var count = Double(queue.count) //get total number of nodes at this new level
            for node in queue {
                if let myNode = node {
                    levelSum = levelSum + Double(myNode.val)
                    queue.removeFirst() //pop already visited value from the queue
                }
            }

            var levelAvg = Double(levelSum / count)
            avg.append(levelAvg)

            //step to new level
            if (current.left != nil) {queue.append(current!.left)} //append left node to queue
            if (current.right != nil) {queue.append(current!.right)} //append right node to queue
            //now repeat for new level
        }
        return avg
    }
这样做:

for node in queue {
    if let myNode = node {
        if let newNum = Double(myNode.val) {
            levelSum += newNum 
        }
        queue.removeFirst() //pop already visited value from the queue
    }
 }

我认为深度优先搜索比广度优先搜索更简单。然后,您可以使用调用堆栈而不是维护自己的队列:

extension TreeNode {

    func levelMeans() -> [Double] {
        var sumAtLevel = [Double]()
        var countAtLevel = [Double]()

        func visit(_ node: TreeNode, level: Int) {
            if sumAtLevel.count == level {
                sumAtLevel.append(0)
                countAtLevel.append(0)
            }

            sumAtLevel[level] += node.val
            countAtLevel[level] += 1

            if let left = node.left { visit(left, level: level + 1) }
            if let right = node.right { visit(right, level: level + 1) }
        }

        visit(self, level: 0)
        return zip(sumAtLevel, countAtLevel).map({ $0.0 / $0.1 })
    }

}

let test0 =
    TreeNode(10,
             TreeNode(5),
             TreeNode(15,
                      TreeNode(6),
                      TreeNode(20)))
print(test0.levelMeans())

# Output: [10.0, 10.0, 13.0]

在我的队列中使用flatMap?当元素是TreeNode类型时,我该如何做呢?如果您将每个值附加到
for
循环中的可选整数数组中,这将起作用。然后,您可以在末尾返回
flatMap
的值。仍然无法通过相同的测试用例:对于队列中的节点{if let myNode=node{if myNode.val!=nil{levelSum=levelSum+Double(myNode.val)}queue.removeFirst()//pop已经访问了队列}中的值或
levelSum+=Double(node?.val??0)
我确实需要更频繁地使用可选链接,它更优雅,仍然无法通过相同的测试用例:对于队列中的节点{if let myNode=node{if myNode.val!=nil{levelSum=levelSum+Double(myNode.val)}queue.removeFirst()//从队列中弹出已访问值}