Given a binary tree, write a function to get the maximum width of the given tree. The width of a tree is the maximum width among all levels. The binary tree has the same structure as a full binary tree, but some nodes are null. 

The width of one level is defined as the length between the end-nodes (the leftmost and right most non-null nodes in the level, where the null nodes between the end-nodes are also counted into the length calculation.

Example 1:

Input: 

           1
         /   \
        3     2
       / \     \  
      5   3     9 

Output: 4
Explanation: The maximum width existing in the third level with the length 4 (5,3,null,9).



Example 2:

Input: 

          1
         /  
        3    
       / \       
      5   3     

Output: 2
Explanation: The maximum width existing in the third level with the length 2 (5,3).



Example 3:

Input: 

          1
         / \
        3   2 
       /        
      5      

Output: 2
Explanation: The maximum width existing in the second level with the length 2 (3,2).


Example 4:

Input: 

          1
         / \
        3   2
       /     \  
      5       9 
     /         \
    6           7
Output: 8
Explanation:The maximum width existing in the fourth level with the length 8 (6,null,null,null,null,null,null,7).




Note:
Answer will in the range of 32-bit signed integer.

Difficulty: interview

Starter code:

# Definition for a binary tree node.
class TreeNode:
    def __init__(self, val=0, left=None, right=None):
    self.val = val
    self.left = left
    self.right = right
class Solution:
    def widthOfBinaryTree(self, root: TreeNode) -> int:
        

Solutions:
class Solution:
     def widthOfBinaryTree(self, root):
         """
         :type root: TreeNode
         :rtype: int
         """
         if not root:
             return 0
         s=1
         a=[[root,1]]
         while 1:
             b=[]
             for p in a:
                 if p[0].left:
                     b.append([p[0].left,2*p[1]-1])
                 if p[0].right:
                     b.append([p[0].right,2*p[1]])
             a=b
             if a:
                 s=max(s,a[-1][1]-a[0][1]+1)
             else:
                 break
         return s

class Solution:
     def widthOfBinaryTree(self, root):
         """
         :type root: TreeNode
         :rtype: int
         """
         
         widths = []
         
         def traverse(root, height, pos):
             nonlocal widths
             if root is None:
                 return
             if len(widths) < (height + 1):
                 widths.append([height, pos, pos])
             else:
                 if widths[height][1] > pos:
                     widths[height][1] = pos
                 if widths[height][2] < pos:
                     widths[height][2] = pos
             if pos == 0:
                 traverse(root.left, 1, -1)
                 traverse(root.right, 1, 1)
             else:
                 traverse(root.left, height + 1, (2 * pos - 1) if pos > 0 else (2 * pos))
                 traverse(root.right, height + 1, (2 * pos) if pos > 0 else (2 * pos + 1))
             
         traverse(root, 0, 0)
         ret = 0
         for width in widths:
             ret = max(ret, (width[2] - width[1]) if width[2] * width[1] < 0 else (width[2] - width[1] + 1))
         return ret
         


class Wrapper:
     def __init__(self, node, val=None):
         self.node = node
         self.val = val
     
     def isInt(self):
         return self.val is not None
     
     def getValue(self):
         if self.node:
             return self.node
         
         return self.val
     
     def addValue(self, val):
         self.val += val
 
 class Solution:
     def testNode(self, node, newStack):
         acc = 0
         
         if node:
             newStack.append(Wrapper(node))
             acc += 1
         elif len(newStack):
             acc += 1
             if newStack[-1].isInt():
                 newStack[-1].addValue(1)
             else:
                 newStack.append(Wrapper(None, 1))
                 
         return acc
     
     def widthOfBinaryTree(self, root):
         """
         :type root: TreeNode
         :rtype: int
         """
         if not root:
             return 0
         
         stack = [Wrapper(root)] 
         res = 1
         
         while len(stack):
             newStack = []
             acc = 0
             
             for node in stack:
                 if node.isInt():
                     if len(newStack):
                         if newStack[-1].isInt():
                             newStack[-1].addValue(2 * node.getValue())
                         else:
                             newStack.append(Wrapper(None, 2 * node.getValue()))
 
                         acc += 2 * node.getValue()
                 else:
                     acc += self.testNode(node.getValue().left, newStack)
                     acc += self.testNode(node.getValue().right, newStack)
                 
             stack = newStack
             if len(newStack) and newStack[-1].isInt():
                 acc -= stack.pop().getValue()
             res = max(res, acc)
                     
         return res

class Solution:
     def widthOfBinaryTree(self, root):
         """
         :type root: TreeNode
         :rtype: int
         """
         if root is None: return 0;
         
         q = [(root, 0)];
         left = 0;
         right = 0;
         res = 1;
         
         while q:
             qLength = len(q);
             
             for i in range(qLength):
                 node, index = q.pop(0);
                 if i == 0:
                     left = index;
                 if i == qLength - 1:
                     right = index;
                 
                 if node.left is not None:
                     q.append((node.left, (2*index)+1));
                 if node.right is not None:
                     q.append((node.right, (2*index)+2));
                     
             res = max(res, right-left+1);
         
         return res;


class Solution:
     def widthOfBinaryTree(self, root):
         """
         :type root: TreeNode
         :rtype: int
         """
         queue = [(root, 0, 0)]
         cur_depth = left = ans = 0
         for node, depth, pos in queue:
             if node:
                 queue.append((node.left, depth+1, pos*2))
                 queue.append((node.right, depth+1, pos*2 + 1))
                 if cur_depth != depth:
                     cur_depth = depth
                     left = pos
                 ans = max(pos - left + 1, ans)
 
         return ans

class Solution:
     def widthOfBinaryTree(self, root):
         """
         :type root: TreeNode
         :rtype: int
         """
         # perform iterative level traversal with null also accounted
         # Notice each node can be represented with depth, position
         # root.left = d+1, pos*2; root.right = d+1, pos*2-1
         if not root: return 0
         queue = collections.deque([[root, 0]])
         ret = 0
         while queue:
             size = len(queue)
             level = []
             for _ in range(size):
                 node, pos = queue.pop()
                 level.append(pos)
                 if node.left: queue.appendleft([node.left, pos*2])
                 if node.right: queue.appendleft([node.right, 1 + pos*2])
             print(level)        
             ret = max(ret, level[-1] - level[0] + 1)        
         return ret    
                    


class Solution:
     def widthOfBinaryTree(self, root):
         """
         :type root: TreeNode
         :rtype: int
         """
         
         def get_max_width(root, width, level, d):
             if not root:
                 return
             
             d[level].append(width)
             # I want the nodes of a level numbered from 0.. 2^n-1
             get_max_width(root.left, 2*width, level + 1, d)
             get_max_width(root.right, 2*width + 1, level + 1, d)
         
         from collections import defaultdict
         d = defaultdict(list)
         
         get_max_width(root, 0, 0, d)
         
         print(d)
         max_width = 0
         for level, elements in list(d.items()):
             if elements: 
                 # if the len of elements is 1 i will still get width 1
                 elements.sort()
                 curr_width = elements[-1] - elements[0] + 1
                 max_width = max(max_width, curr_width)
         
         return max_width
             


class Solution:
     
     
     def widthOfBinaryTree(self, root):
         """
         :type root: TreeNode
         :rtype: int
         """
         if not root: return 0
 
         maxlen=1
         start=1
         end=1
         tlen=1
         l=[[root,1]]
         
         while tlen:
             llen=tlen
             tlen=0
             while llen:
                 cur=l.pop(0)
                 llen-=1
                 if cur[0]:
                     l.append([cur[0].left,2*cur[1]-1])
                     l.append([cur[0].right,2*cur[1]])
                     tlen+=2
 
             if len(l)>0:
                 for item in reversed(l):
                     if item[0]:
                         end=item[1]
                         break
                 if end != item[1]: return maxlen
                 
                 for item in l:
                     if item[0]:
                         start=item[1]
                         break;
                 
                 end = end - start + 1
                 if(end > maxlen):  maxlen=end
                 
                 start=end=-1;
                 
         return maxlen

class Solution:
     def widthOfBinaryTree(self, root):
         """
         :type root: TreeNode
         :rtype: int
         """
         queue = [(root, 0, 0)]
         cur_depth = left = ans = 0
         for node, depth, pos in queue:
             if node:
                 queue.append((node.left, depth + 1, 2*pos))
                 queue.append((node.right, depth + 1, 2*pos + 1))
                 if cur_depth != depth:
                     cur_depth = depth
                     left = pos
                 ans = max(pos - left + 1, ans)
         return ans


class Solution:
     
     
     def widthOfBinaryTree(self, root):
         """
         :type root: TreeNode
         :rtype: int
         """
         if not root: return 0
 
         maxlen=1
         start=1
         end=1
         tlen=1
         l=[[root,1]]
         
         while tlen:
             llen=tlen
             tlen=0
             while llen:
                 cur=l.pop(0)
                 llen-=1
                 if cur[0]:
                     l.append([cur[0].left,2*cur[1]-1])
                     l.append([cur[0].right,2*cur[1]])
                     tlen+=2
 
             if len(l)>0:
                 for item in reversed(l):
                     if item[0]:
                         end=item[1]
                         break
                 if end != item[1]: return maxlen
                 
                 for item in l:
                     if item[0]:
                         start=item[1]
                         break;
                 
                 end = end - start + 1
                 if(end > maxlen):  maxlen=end
                 
                 start=end=-1
                 
         return maxlen

class Solution:
     def isInt(self, e):
         return type(e).__name__ == 'int'
     
     def testNode(self, node, newStack):
         acc = 0
         
         if node:
             newStack.append(node)
             acc += 1
         elif len(newStack):
             acc += 1
             if self.isInt(newStack[-1]):
                 newStack[-1] += 1
             else:
                 newStack.append(1)
                 
         return acc
     
     def widthOfBinaryTree(self, root):
         """
         :type root: TreeNode
         :rtype: int
         """
         if not root:
             return 0
         
         stack = [root] 
         res = 1
         
         while len(stack):
             newStack = []
             acc = 0
             
             for node in stack:
                 if self.isInt(node):
                     if len(newStack):
                         if self.isInt(newStack[-1]):
                             newStack[-1] += 2 * node
                         else:
                             newStack.append(2 * node)
 
                         acc += 2 * node
                 else:
                     acc += self.testNode(node.left, newStack)
                     acc += self.testNode(node.right, newStack)
                 
             stack = newStack
             if len(newStack) and self.isInt(newStack[-1]):
                 acc -= stack.pop()
             res = max(res, acc)
                     
         return res

class Solution:
     def widthOfBinaryTree(self, root):
         """
         :type root: TreeNode
         :rtype: int
         """
         
         table = {}
         
         stack = [(root, [])]
         while stack:
             node, path = stack.pop()
             if not node:
                 continue
             
             table.setdefault(len(path), []).append(path)
             
             stack.append((node.left, path + ['0']))
             stack.append((node.right, path + ['1']))
             
         
         maxwidth = 0
         for n in sorted(table):
             paths = table[n]
             if len(paths) < 1:
                 continue
             if len(paths) == 1:
                 maxwidth = max(1, maxwidth)
                 continue
                 
             values = list(map(lambda p: int(''.join(p), 2), paths))
             width = max(values) - min(values) + 1
             
             maxwidth = max(maxwidth, width)
             
         return maxwidth