如何在Swift中指定和展开可选阵列对象?

如何在Swift中指定和展开可选阵列对象?,swift,binary-tree,optional,Swift,Binary Tree,Optional,我正在尝试使用迭代方法在Swift中反转二叉树。基本上,我只是在每个节点之间循环,并将其放入堆栈数组中。此数组应该是可选节点的数组。这是我的密码: func invertTree(_ root: TreeNode?) -> TreeNode? { if root != nil { stack.append(root) } else { return root } var

我正在尝试使用迭代方法在Swift中反转二叉树。基本上,我只是在每个节点之间循环,并将其放入堆栈数组中。此数组应该是可选节点的数组。这是我的密码:

 func invertTree(_ root: TreeNode?) -> TreeNode? { 
        if root != nil {
            stack.append(root) 
        } else {
            return root
        }

        var stack = [TreeNode?]()
        while stack.count > 0 {
            if stack.last == nil {
                stack.removeLast()
            } else {

                var tempLeft : TreeNode? = stack.last!.left
                stack.last!.left = stack.last!.right
                stack.last!.right = tempLeft

                if stack.last!.left != nil {
                    stack.append(stack.last!.left)
                }

                if stack.last.right != nil {
                    stack.append(stack.last!.right)
                }
            }
        }
        return root
}
我得到了各种各样的可选错误。特别是,当我设置:

var tempLeft : TreeNode? = stack.last!.left
我不知道为什么它会说“可选类型TreeNode的值?必须展开才能引用solution.swift中展开的基类型“TreeNode”的成员“left”

我不明白为什么它告诉我打开可选的,而我已经在强制打开它。我不想打开.left节点,因为我想在堆栈中包含nils,以便迭代工作


任何帮助都将不胜感激

stack.last
是一个双重可选的TreeNode:
TreeNode???

您可以使用如下可选链接:

if stack.last == nil {
    stack.removeLast()
} else {
    stack.last
    var tempLeft : TreeNode? = stack.last!?.left
    stack.last!?.left = stack.last!?.right
    stack.last!?.right = tempLeft

    if stack.last!?.left != nil {
        stack.append(stack.last!?.left)
    }

    if stack.last??.right != nil {
        stack.append(stack.last!?.right)
    }
}
或者避免戏剧化,使用模式匹配:

if case let node?? = stack.last {
    let tempLeft = node.left
    node.left = node.right
    node.right = tempLeft

    ...

除此之外,您的代码似乎还有其他方面需要改进。例如,在声明之前使用
stack


替代实施 下面是一个使用堆栈的解决方案:

class Solution {
    func invertTree(_ root: TreeNode?) -> TreeNode? {

        guard let r = root else {
            return nil
        }

        var stack = [r]

        while let node = stack.last {
            let temp   = node.left
            node.left  = node.right
            node.right = temp

            stack.removeLast()

            if let left  = node.left  { stack.append(left)  }
            if let right = node.right { stack.append(right) }
        }

        return r
    }
}

将条件
if stack.last==nil{
更改为
let last=stack.last{
(并交换if和else逻辑)以获得更快速的方法,然后使用
last
变量而不需要任何展开。为什么堆栈需要是
[TreeNode?]
而不仅仅是
[TreeNode]
?非常感谢!我想给你投票,但我只有14个因果报应,所以它不会影响评级!但我想知道你是否可以解释第一个guard语句。如果我不使用该guard语句,而是使用guard root!=nil,我会得到一个错误。将根初始化为自身会打开它吗?不客气!如果这个答案解决了问题,请回答在代码中,您可以通过单击复选标记来编码并接受它。享受编码!
guard let root=root else{return nil}
使用可选绑定,如果
root
不是
nil
,则初始化一个新变量,该变量恰好与
root
同名,您可以将其称为
r
或任何您觉得正常的名称。在代码的其余部分,您将引用此新变量,而不是初始的
root
清楚,我将编辑答案。