Leetcode117 填充同一兄弟结点II

不得不说,之前在做[116 填充同一兄弟节点I]的时候,没有思考那么多,被做题的兴奋冲昏了头脑,很想当然的把题目I的完全树想象成可以用完全树绝对坐标的性质做点事情。但到题目二的时候,我才发现这个问题的纠结所在。如果不是完全树,树中的某些结点为空的话,用题目I的算法是跑不通的。

 

分析

如果有同学和我一样,最开始用先序遍历来解决这个问题的话,就会遇到和我一样的问题,如上图所示。按照先序序列的话,第一个处理链接的结点为B,然后为D,都能正确的找到链接对象,问题在于D后续的G,这个点从图上看是应该链接到H的,但是我们却做不到这一点。因为H的双亲为F,而应该链接到F的E节点在先序序列中是处于G之后的,处理自己的时候,需要的先决条件还没有被计算。而之前在题目一中之所以可以,是因为每个节点的链接要么是自己的亲兄弟节点(双亲节点的右孩子),要么是表兄弟(双亲节点兄弟节点的左孩子),而这两种节点,在遍历到自己时,都是可以访问到的。

思考

所以这次必须要一层一层的去遍历了。这个时候我们还是得回到之前说的,如果用队列来实现一个层次遍历,这个题目就没有难度了。但是队列需要占用额外的空间,所以不符合题目的要求。那是不是说,只要不消耗这个空间,仍然用队列层次遍历的思想就可以达到目的呢?是的。

我们得思考的一个问题是,队列到底维护了什么?一个先后顺序。我们总是从队列中取出一个结点,然后把它的子节点加入到队列中去,子节点仍然是符合顺序的。

再看看上图我们发现,每一行的链接自然的构成了每一行的结点序列。而每一行的结点序列的孩子的序列,恰好是下一行的所有结点。所以这个题目可以迭代的利用每一行的链接信息来生成下一行信息。

这个也是看了别人解决方案之后的解释,想到这一点也不容易吧。

算法

这个题目还需要用到一点小技巧,要用到链表的知识。

问题解决涉及两个链表,一个链表用来遍历当前层。另一个链表用来生成下一层的链接

用带头节点的链表来简化操作

1、初始化遍历结点为root,通过root->next构成了一个初始的遍历序列 curLevel

2、若curLevel不为空则执行3,否则结束算法

3、遍历curLevel,并将curLeve中每个节点的左右孩子(如果有),插入到下一层的遍历序列NextLevel中。NextLevel中的链接由孩子节点的next构成。

4、将NextLevel序列赋值给curLevel,跳转到2

代码

class Solution {
public:
    void connect(TreeLinkNode *root) {
        TreeLinkNode *cur = root;
        while (cur != NULL) {
            TreeLinkNode *dummy = new TreeLinkNode(-1);
            TreeLinkNode *pre = dummy;
            while (cur) {
                cur->left && (pre->next = cur->left, pre = cur->left);
                cur->right && (pre->next = cur->right, pre = cur->right);
                cur = cur->next;
            }
            cur = dummy->next;
        }
    }
};

分析:其中用到了高级语言的短路逻辑来简化代码。在&&表达始中,如果前半部分为假,则不会执行后半部分逻辑。后半部分用到了逗号表达式,但因为这个表达始终我们并不关心布尔值,所以语句本身产生的值并不需要考虑

总结

我们做题总是在努力提高自己的算法思维,计算思维,但经常会被自己的套路所局限。自己想破脑袋想不出来,看了答案又觉得,哎呀,为何会如此简单。我想一部分原因是因为学的太死。比如用队列去实现层次遍历,整个思维重心都在队列上,而忽略了本质,本质是一种序列关系,是一种可以按顺序得到节点孩子的关系。队列只是手段不是目的。没有思考太多,看透本质就造成不懂得变通,举一不能反三。这部分能力还是需要一直去加强和训练的。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值