Leetcode 学习计划之21天算法 (八)

第8天 广度优先搜索 / 深度优先搜索 

注意:DFS、BFS都可以用seen数组记录是否访问。其中图问题一般都要用seen数组,因为图有回路。而二叉树不一定用seen数组,因为树没有回路,不会重复访问陷入无限循环。 

617.合并二叉树

1、BFS。不用额外空间,直接在其中一棵树上操作即可。出队时,判断两棵树的左儿子是否都有,只有root1有,只有root2有,都没有这四种情况,右儿子同理。都有就都入队。否则不用入队。

2、DFS。DFS版本,相较于DFS版本,仅做了一处修改,即把pop(0)改成了pop()  #即pop(-1).

#BFS版本
# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution(object):
    def mergeTrees(self, root1, root2):
        """
        :type root1: TreeNode
        :type root2: TreeNode
        :rtype: TreeNode
        """
        if not(root1 and root2):
            if not root1:
                return root2
            else:
                return root1

        queue = []
        queue.append([root1, root2])
        root1.val = root1.val + root2.val
        while queue:
            i,j = queue.pop(0)
            if i.left and j.left:
                i.left.val = i.left.val + j.left.val
                queue.append([i.left,j.left])
            elif i.left:
                i.left = i.left
            elif j.left:
                i.left = j.left
            else:
                i.left = None

            if i.right and j.right:
                i.right.val = i.right.val + j.right.val
                queue.append([i.right,j.right])
            elif i.right:
                i.right = i.right
            elif j.right:
                i.right = j.right
            else:
                i.right = None

        return root1
#DFS版本,相较于DFS版本,仅做了一处修改,即把pop(0)改成了pop()  #即pop(-1).
#这样就把queue队列变成了stack栈,也就把BFS变成了DFS
# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution(object):
    def mergeTrees(self, root1, root2):
        """
        :type root1: TreeNode
        :type root2: TreeNode
        :rtype: TreeNode
        """
        if not(root1 and root2):
            if not root1:
                return root2
            else:
                return root1

        queue = []
        queue.append([root1, root2])
        root1.val = root1.val + root2.val
        while queue:
            i,j = queue.pop()
            if i.left and j.left:
                i.left.val = i.left.val + j.left.val
                queue.append([i.left,j.left])
            elif i.left:
                i.left = i.left
            elif j.left:
                i.left = j.left
            else:
                i.left = None

            if i.right and j.right:
                i.right.val = i.right.val + j.right.val
                queue.append([i.right,j.right])
            elif i.right:
                i.right = i.right
            elif j.right:
                i.right = j.right
            else:
                i.right = None

        return root1

116.填充每个节点的下一个右侧节点指针

 

 思路:

判断一个数是否为2的幂数。

//将2的幂写成二进制很容易看出,2的幂的二进制只有一个1,其余全是0,如下所示:
//000010000…00
//而将2的幂的二进制减1,其二进制变为:
//000001111…11
//所以判断一个数是不是2的幂的方法为使用按位与操作,如果结果为0,则是2的幂:
//n & (n-1)
//代码如下
//方法1

bool is_2power(int num)
{
    return !(num & (num-1));//这里负数也会判断为非2的幂,负数最高位为1
}
//方法2
bool is_2power(int num)
{
    if(num < 0) return false; //负数都不会是2的幂
    while(num != 1){    //2的0次幂为1
        if(num%2 != 0)
            return false;
        num /= 2;
    }
    return true;
}

1、BFS,判断一下当前队列的长度是否为2的幂数,如果是当前结点右儿子的next为None,否则为队头结点的左儿子节点。

"""
# Definition for a Node.
class Node(object):
    def __init__(self, val=0, left=None, right=None, next=None):
        self.val = val
        self.left = left
        self.right = right
        self.next = next
"""

class Solution(object):
    def connect(self, root):
        """
        :type root: Node
        :rtype: Node
        """
        if not root:
            return root
        queue = []
        queue.append(root)
        while(queue):
            tmp = queue.pop(0)
            if tmp.left:
                queue.append(tmp.left)
                tmp.left.next = tmp.right                
            if tmp.right:
                queue.append(tmp.right) 
                num = len(queue)                
                flag = (num & (num-1))                                   
                if not flag:
                    tmp.right.next = None
                else:
                    tmp.right.next = queue[0].left
                     
        return root

 2、层次遍历.

(1)不像BFS一样每次只pop队头,而是把这一层都pop出来。

#层次遍历,每次处理当前层的下一层
"""
# Definition for a Node.
class Node(object):
    def __init__(self, val=0, left=None, right=None, next=None):
        self.val = val
        self.left = left
        self.right = right
        self.next = next
"""

class Solution(object):
    def connect(self, root):
        """
        :type root: Node
        :rtype: Node
        """
        if not root:
            return root
        queue = []
        queue.append(root)
        while(queue):
            size = len(queue)
            for i in range(size):
                tmp = queue.pop(0)
                if tmp.left:
                    queue.append(tmp.left)
                    tmp.left.next = tmp.right                
                if tmp.right:
                    queue.append(tmp.right)                                   
                    if i == size-1:
                        tmp.right.next = None
                    else:
                        tmp.right.next = queue[0].left                     
        return root

        

(2)层次遍历,每次处理当前层。 

"""
# Definition for a Node.
class Node(object):
    def __init__(self, val=0, left=None, right=None, next=None):
        self.val = val
        self.left = left
        self.right = right
        self.next = next
"""

class Solution(object):
    def connect(self, root):
        """
        :type root: Node
        :rtype: Node
        """
        if not root:
            return root
        queue = []
        queue.append(root)
        while(queue):
            size = len(queue)
            for i in range(size):
                tmp = queue.pop(0)
                if i <size-1:
                    tmp.next = queue[0] #一层的直接用next指向队头
                if tmp.left:
                    queue.append(tmp.left)                            
                if tmp.right:
                    queue.append(tmp.right)                                                    
        return root

3、递归

class Solution(object):
    def connect(self, root):
        """
        :type root: Node
        :rtype: Node
        """
        if not root:
            return root
        def dfs(Node):
            if not (Node.left):
                return
            Node.left.next = Node.right
            dfs(Node.left)
            if Node.next:                        #如果Node有next结点
                Node.right.next = Node.next.left     #Node右儿子的next结点为Node的next结点的左儿子       
            dfs(Node.right)
        dfs(root)                                                  
        return root

4、迭代的O(1)空间解法:

#外循环:纵向遍历用ceng=ceng.left向下一层
#内循环:横向遍历用pre=pre.next向右一个
class Solution(object):
    def connect(self, root):
        """
        :type root: Node
        :rtype: Node
        """
        if not root:
            return root
        ceng = root #ceng指示纵向遍历到树的哪一层了
        while ceng.left: #直到最后一层
            pre = ceng   #pre记录当前层,一直遍历到当前层的末尾
            while pre:           
                pre.left.next = pre.right
                if pre.next:
                    pre.right.next = pre.next.left
                pre = pre.next
            ceng = ceng.left                                                
        return root

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值