Binary Tree Level Order Traversal - BFS - Leetcode 102

SdĂ­let
VloĆŸit
  • čas pƙidĂĄn 2. 03. 2021
  • 🚀 neetcode.io/ - A better way to prepare for Coding Interviews
    🐩 Twitter: / neetcode1
    đŸ„· Discord: / discord
    🐼 Support the channel: / neetcode
    Coding Solutions: ‱ Coding Interview Solut...
    Dynamic Programming Playlist: ‱ House Robber - Leetco...
    Tree Playlist: ‱ Invert Binary Tree - D...
    Linked List Playlist: ‱ Reverse Linked List - ...
    Problem Link: neetcode.io/problems/level-or...
    0:00 - Read the problem
    leetcode 102
    This question was identified as an interview question from here: github.com/xizhengszhang/Leet...
    #sorted #array #python
  • Věda a technologie

Komentáƙe • 106

  • @Asdelatech
    @Asdelatech Pƙed 24 dny +5

    This is the first time I was able to solve a tree-based leetcode medium problem on my own. Clearly, I am making progress every day. Thank you, man!!!

  • @lovleenkaur1042
    @lovleenkaur1042 Pƙed 3 lety +66

    Please make more such videos! Your explanation is super easy to be grasped. Thanks a lot for putting on the effort

    • @NeetCode
      @NeetCode  Pƙed 3 lety +12

      Thank you, I will :)

  • @kockarthur7976
    @kockarthur7976 Pƙed rokem +5

    It is actually totally fine to do Depth First Search for this problem, because it is not necessary that we actually TRAVERSE the list level-by-level, despite the problem name "Level Order Traversal". We only need to output the list of node lists organized by level and ordered left-to-right.

  • @anjaliyadav9360
    @anjaliyadav9360 Pƙed 2 lety +12

    I usually see your solutions after trying out myself. Almost always get a new way to solve. Keep it up!

  • @NeetCode
    @NeetCode  Pƙed 3 lety +3

    Tree Playlist: czcams.com/video/OnSn2XEQ4MY/video.html

    • @varunshrivastava2706
      @varunshrivastava2706 Pƙed 2 lety

      Hey can you tell me for this question why did we wrote q.append(root) instead of q.append(root.val)?

    • @lordsixth5944
      @lordsixth5944 Pƙed 2 lety

      @@varunshrivastava2706 it has been three month but still
      We are appending root not root.val cause after appending we have to iterate over it to get it's childrens hope it helps

    • @taymurnaeem50
      @taymurnaeem50 Pƙed rokem

      @@varunshrivastava2706 Because we need entire root node, along with its all children and grandchildren and so on.. Not just root node value.

    • @varunshrivastava2706
      @varunshrivastava2706 Pƙed rokem

      @@taymurnaeem50 yeah now I know that, god I was really dumb a year ago😂😂😂

    • @servantofthelord8147
      @servantofthelord8147 Pƙed 28 dny

      @@varunshrivastava2706 You weren't dumb, you were just getting started :)

  • @Sethsm1
    @Sethsm1 Pƙed 2 lety +2

    Very clean and clear explanation, thanks!

  • @davisward3144
    @davisward3144 Pƙed 2 lety +2

    your code is so clean. thanks so much!

  • @akshaygupta8332
    @akshaygupta8332 Pƙed 2 lety

    Excellent explanation! Thanks a lot!!

  • @MichaelShingo
    @MichaelShingo Pƙed rokem +1

    ooo I got the BFS part but really the key to the problem is to know when each level ends thanks

  • @mehershrishtinigam5449
    @mehershrishtinigam5449 Pƙed 2 lety +8

    First time I'm hearing someone call deque as "deck" and honestly that makes so much sense. Otherwise most people I know pronounce dequeue and deque the same, which can be confusing.

  • @jonaskhanwald566
    @jonaskhanwald566 Pƙed 3 lety +13

    Now this solution is:
    Runtime: 20 ms, faster than 99.87% of Python3 online submissions for Binary Tree Level Order Traversal.
    Memory Usage: 14.3 MB, less than 96.23% of Python3 online submissions for Binary Tree Level Order Traversal.

  • @user-dc7oj3el7o
    @user-dc7oj3el7o Pƙed 2 lety

    such a clear explanation! Thank you 👍

  • @vinaf4494
    @vinaf4494 Pƙed rokem +17

    "The pop() method is used to remove and return the right most element from the queue, and popleft() method is used to remove and return left most element from the queue."
    Just a note to explain line 18, the ".popleft()"

    • @seenumadhavan4451
      @seenumadhavan4451 Pƙed 8 měsĂ­ci

      You can pass list.pop(index)
      This will work for sure 😊

  • @Daedalus675
    @Daedalus675 Pƙed 2 lety +4

    Def the best coding channel on yt. There's a reason why he's at Google.

  • @viceroyop6385
    @viceroyop6385 Pƙed 2 lety +2

    I solved this using list as a stack with Python, since it's a stack and not a queue you would want to append the right child of each node before the left child so when you pop, you pop left child first for the correct ordering.

  • @vandananayak9426
    @vandananayak9426 Pƙed 2 lety

    Thank you for all the good work

  • @patrickfeeney4180
    @patrickfeeney4180 Pƙed 3 měsĂ­ci

    Checking how many loops to do before you start the for-loop and then just looping that amount of times without looking at the queue at all as the condition for the loop is just so smart ffs. Fair play.

  • @colinrickels201
    @colinrickels201 Pƙed rokem +3

    I think it’s worth noting that with a binary tree, it’s more ideal to recursively feed the next left node through before moving on the right as a means of BFS. Given that this is the algo for any n tree though, I’m also seeing the benefit of prioritizing this approach.

    • @yinglll7411
      @yinglll7411 Pƙed 2 měsĂ­ci

      hi @colinrickels201 I think what you are proposing is a DFS rather than BFS, which will make it difficult to keep track of which level of the tree you are currently in and preserve the order of nodes across each level.

  • @minciNashu
    @minciNashu Pƙed 2 lety +10

    you can do range(len(q)) safely. the range wont change dinamically.
    also, i think it's better to check left and right for none before appending, this way you dont add null nodes to queue.

    • @nasdas123
      @nasdas123 Pƙed rokem +1

      agreed, here-s my solution:
      class Solution:
      def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
      resList = []
      q = collections.deque()
      if root:
      q.append(root)
      while q:
      level = []
      qLen = len(q)
      for node in range(qLen):
      cur = q.popleft()
      if cur.left:
      q.append(cur.left)
      if cur.right:
      q.append(cur.right)
      level.append(cur.val)
      resList.append(level)
      return resList

  • @WaldoTheWombat
    @WaldoTheWombat Pƙed měsĂ­cem +1

    My version (checking if the children are not None instead of checking the node itself):
    if root is None:
    return []
    q = deque()
    q.append(root)
    levels_vals = []

    while q:
    level_length = len(q)
    values = []
    for current_level_nodes_count in range(level_length):
    node = q.popleft()
    values.append(node.val)
    if node.left:
    q.append(node.left)
    if node.right:
    q.append(node.right)
    levels_vals.append(values)
    return levels_vals

  • @expansivegymnast1020
    @expansivegymnast1020 Pƙed rokem

    Good explanation. I solved number of islands, and 01 Matrix and then got stuck on this problem.

  • @shristyagarwal3812
    @shristyagarwal3812 Pƙed 9 měsĂ­ci +1

    The idea is the same. The way I solved it feels more intuitive-
    def rightSideView(self, root: Optional[TreeNode]) -> List[int]:
    ans = []
    if not root:
    return ans
    bQ = [(root, 0)]
    prevL = -1
    while bQ:
    n, level = bQ.pop(0)
    if prevL != level:
    ans.append(n.val)
    prevL = level
    if n.right:
    bQ.append((n.right, level + 1))
    if n.left:
    bQ.append((n.left, level + 1))
    return ans

  • @whonayem01
    @whonayem01 Pƙed 2 lety

    Nice solution!

  • @namanvohra8262
    @namanvohra8262 Pƙed 2 lety

    Nice video as usual! But why did u add another condition of if Level?

  • @kirillzlobin7135
    @kirillzlobin7135 Pƙed 10 měsĂ­ci

    You are super talented to explain such complex stuff in a soo easy-to-understand way... This is amazing

  • @The6thProgrammer
    @The6thProgrammer Pƙed 9 měsĂ­ci +7

    There is no need to check if level is empty before appending it to the result. The only way our while loop iterates is if the q contains >= 1 nodes. Therefore you are always appending at least a single node to the level list.

    • @ilang747
      @ilang747 Pƙed 14 dny

      There is a need. It is for last nodes in q. There will be [None,None,None,None] . It is True in Python. That is why last run will add empty list to res

  • @sarvarjuraev1376
    @sarvarjuraev1376 Pƙed měsĂ­cem

    Thanks a lot for clear explanation

  • @JohnnyMetz
    @JohnnyMetz Pƙed 2 lety +1

    Any reason why you're using collections.deque() instead of queue.Queue() ? Is one faster than the other?

  • @mikemihay
    @mikemihay Pƙed 3 lety

    Thank you !

  • @sundararajannarasiman5613

    Nice video on BFS

  • @monicawang8447
    @monicawang8447 Pƙed 2 lety +16

    i have a dumb question: why does the length of queue not change even though we append the left and right child nodes?

    • @NeetCode
      @NeetCode  Pƙed 2 lety +13

      That's a good question, it use to confuse me as well.
      Think of it in terms of passing a value (in this case the queue length) into a function.
      Basically, the for loop's range() is a function, and we are only calculating the length of the queue a single time and passing it into the range() function.

    • @cgqqqq
      @cgqqqq Pƙed 2 lety +2

      queue的长ćșŠäž€ç›Žæ˜Żćœšæ”čć˜çš„ïŒŒæŻäžȘwhilećŸȘçŽŻéƒœäŒšpopæŽ‰ćœ“ć‰level所有的nodeïŒŒäœ†æ˜ŻäŒšćœšćŽéąćŠ äžŠchildren的nodeäżĄæŻ (虜然有äș›nodeæ˜Żnone)ïŒŒäœ†æ˜Żç”±äșŽè§„ćźšäș†for i in range(len(q))ïŒŒćœšäœ çš„queueæŽ„è§Šćˆ°children的nodeäżĄæŻäč‹ć‰ïŒŒæœŹæŹĄćŸȘ环氱ć·Čç»ç»ˆæ­ąäș†ă€‚所仄queuećœšæŻäžȘwhilećŸȘçŽŻéƒœæ˜Żæ›Žæ–°ć…ƒçŽ çš„ă€‚äœ ćœšwhilećŽéąćŠ ć…„printć°±èƒœçœ‹çš„ćŸˆæž…æ„šïŒš
      while q:
      print(len(q)) # print number of elements in queue in the beginning of this iteration
      print(q)

    • @rishabhnegi9806
      @rishabhnegi9806 Pƙed 2 lety +10

      well it is changing as a matter of fact, it's just we are not using the updated queue size

    • @souravbanerjee6457
      @souravbanerjee6457 Pƙed rokem

      think of it like after passing the length of the queue to range() function, it converts it into a for loop of 0 to 4( say ), so here we don't have anything to do with the increasing queue size anymore but have to deal with it again when the loop initializes, you can also try it using forEach it also does the same thing.

  • @pavelmaisiuk-dranko746
    @pavelmaisiuk-dranko746 Pƙed 2 lety

    Thanks for explanation)

  • @johnpaul4301
    @johnpaul4301 Pƙed 3 lety

    Thanks mate

  • @hhcdghjjgsdrt235
    @hhcdghjjgsdrt235 Pƙed rokem

    King of algo, my man

  • @VirtualKnowledgeHub
    @VirtualKnowledgeHub Pƙed rokem

    Hi,
    How Leetcode executes program with default tree definition and other default definations?
    I mean on local machine we define Tree class & initiate it's instance then we call the method with instance name & arguments.
    Here, w/o creating instance & w/o providing values how does it work?
    How to run this code on local machine without full code.
    Please guide me on this.

  • @joshuamarcano350
    @joshuamarcano350 Pƙed 2 lety

    What are you using to do your blackboarding ?

  • @majesticflyingbrick
    @majesticflyingbrick Pƙed rokem

    In your explanation you did not add null nodes into the queue, but in your code you did.

  • @jugsma6676
    @jugsma6676 Pƙed 3 měsĂ­ci +1

    I used dfs, with cache:
    def solution(root):
    cache = {}
    return helper(root, cache, 1)
    def helper(root, cache, l):
    if not root:
    return []
    if l not in cache:
    cache[l] = [root.val]
    else:
    cache[l].append(root.val)
    helper(root.left, cache, l+1)
    helper(root.right, cache, l + 1)
    return list(cache.values())

  • @n.h.son1902
    @n.h.son1902 Pƙed 7 měsĂ­ci

    7:45 I wonder why you said it is possible for the node could be null?

  • @jackpott1322
    @jackpott1322 Pƙed 7 měsĂ­ci

    When i use list instead of deque in this problem i get two times better processing time. it looks like list sometimes is more efficient than deque?

  • @jeffjames15
    @jeffjames15 Pƙed 11 měsĂ­ci

    In the deque, I firstly thought if the left most element is popped, the index 0 will be automatically assigned to the second element, then the for loop will make no sense. It was just my misconception in my imagination, don’t know why I thought like that.😅

  • @AbhishekSingh-rs6tx
    @AbhishekSingh-rs6tx Pƙed 2 lety

    Using queue:
    def levelOrder(self,root):
    if root is None:
    return

    q = deque()
    q.append(root)
    while (len(q)>0):
    root = q.popleft()
    print(root.val,end=" ")
    if(root.left is not None):
    q.append(root.left)

    if(root.right is not None):
    q.append(root.right)

  • @andregabriel5246
    @andregabriel5246 Pƙed rokem

    Hey, great explanation! Just a correction for what was mentioned at 6:17 : the biggest level can have at most (n+1)/2 nodes, and not n/2. This leads also to O(n) space complexity, so it does not make the final analysis wrong :)

  • @jvarunbharathi9013
    @jvarunbharathi9013 Pƙed rokem

    Shouln't the time complexity be O(logn*n) because the forloop can run n/2 times at most and while loop runs log(n)(no of levels in tree) so isn't supposed to be O(n*logn).

  • @nagendrabommireddi8437
    @nagendrabommireddi8437 Pƙed rokem

    thank you sir

  • @daniellim1212
    @daniellim1212 Pƙed rokem +1

    5:49 not a bst

  • @pragyachauhan
    @pragyachauhan Pƙed 3 lety

    What whiteboard do you use for explanations?

    • @NeetCode
      @NeetCode  Pƙed 3 lety +2

      I use Paint3D

    • @chair_smesh
      @chair_smesh Pƙed 2 lety

      @@NeetCode Did google let you use Paint3D for remote interviews?

  • @lemonke8132
    @lemonke8132 Pƙed rokem

    My dfs solution:
    class Solution:
    def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
    results = []

    def preOrder(node, level):
    if not node:
    return
    if level == len(results):
    results.append([node.val])
    else:
    results[level].append(node.val)

    preOrder(node.left, level + 1)
    preOrder(node.right, level + 1)

    preOrder(root, 0)
    return results

  • @saumyaverma9581
    @saumyaverma9581 Pƙed 3 lety +1

    In the while condition if I say "while queue != None"" it was giving me "memory limit exceeded" not when I put "while queue:" it's accepted but what's the difference?

  • @noumaaaan
    @noumaaaan Pƙed 2 lety +1

    Are we allowed to use libraries like collections in coding interviews? Someone please let me know!

    • @NeetCode
      @NeetCode  Pƙed 2 lety +6

      Most of the time yes, unless the question specifically wants you to implement the underlying Data structure or algorithm

  • @edwardteach2
    @edwardteach2 Pƙed 2 lety

    U a God

  • @laveshchanchawat6983
    @laveshchanchawat6983 Pƙed 2 lety

    int size = queue.size(); if we remove this line and directly use for(int i = 0; i < queue.size(); i++) why the output are different?

    • @rishabhnegi9806
      @rishabhnegi9806 Pƙed 2 lety

      Maybe it's bcz your queue size is increasing with each loop because of the push operations of the child nodes instead it should have been constant { i.e. loop should have run only up to the previous size of the queue before pushing nodes left, right child nodes into it} 
 we are doing so because here as u can see we have to create list for every level and return a list with each level s its sub-list 
in order to achieve that we are only running the loop till the size of every level ....but in your case instead of using the initial queue size as loop's limit your loop is running up to updated queue size which not only contains the node of the level but also some of their children's as well

    • @laveshchanchawat6983
      @laveshchanchawat6983 Pƙed 2 lety

      @@rishabhnegi9806 thank you bhai,par Hindi mai bata dete😅.jyada samaz ni aya.

  • @shalsteven
    @shalsteven Pƙed 2 lety

    You are so smart.

  • @director8656
    @director8656 Pƙed 3 lety

    is there a recursive solution to this problem, great video as usual!

    • @saadwaraich1994
      @saadwaraich1994 Pƙed 3 lety +1

      levels = collections.defaultdict(list)
      def dfs(node, level):
      if not node:
      return
      levels[str(level)].append(node.val)
      dfs(node.left, level+1)
      dfs(node.right, level+1)
      dfs(root, 0)
      return levels.values()

    • @director8656
      @director8656 Pƙed 2 lety

      @@saadwaraich1994 thanks a ton!

    • @roderickdunn2517
      @roderickdunn2517 Pƙed 2 lety +1

      @@saadwaraich1994 I don't think there's any need to use a dictionary or collection. Your 'levels' var could just be a plain list, with each index representing the corresponding level. Guess the only caveat is you have to check whether to append another sub-array on each iteration.

    • @erik-sandberg
      @erik-sandberg Pƙed 2 lety

      @@roderickdunn2517
      def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
      levels = []
      # Depth first search
      # At each depth, append value to that element in the array

      def dfs(node, depth):
      if not node:
      return
      if len(levels) == depth:
      levels.append([])
      levels[depth].append(node.val)
      dfs(node.left, depth+1)
      dfs(node.right, depth+1)

      dfs(root, 0)
      return levels

  • @danielbzhang3280
    @danielbzhang3280 Pƙed rokem

    Please make a video about max Width Of Binary Tree please

  • @goodhuman1
    @goodhuman1 Pƙed 6 měsĂ­ci +1

    Thanks a lot man ❀

  • @keremserttas5898
    @keremserttas5898 Pƙed 9 měsĂ­ci

    Hi, how can I implement the same solution using depth first search

    • @keremserttas5898
      @keremserttas5898 Pƙed 9 měsĂ­ci +1

      found my solution
      res = []
      #DFS Solution
      def dfs(head,level):
      if head == None:
      return
      if len(res)

  • @arina1193
    @arina1193 Pƙed 7 měsĂ­ci

    def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
    q = deque([(root, 0)])
    res = []
    while q:
    node, level = q.popleft()
    if not node: continue
    if level == len(res): res.append([])
    res[level].append(node.val)
    q.append((node.left, level + 1))
    q.append((node.right, level + 1))
    return res

  • @jaysonp9426
    @jaysonp9426 Pƙed 9 měsĂ­ci +1

    I was with you until I saw how you name variables

  • @taran7649
    @taran7649 Pƙed 2 lety

    Can we use DFS TOO 
?

    • @supriyamanna715
      @supriyamanna715 Pƙed 2 lety

      No buddy. BSF is level wise search. DFS goes to the depth

    • @BlakeTB
      @BlakeTB Pƙed rokem

      @@supriyamanna715 I believe someone else commented a dfs solution but it’s not as intuitive

  • @pengyan1906
    @pengyan1906 Pƙed rokem +2

    line 21-22, if node.left/right do not exist, will q not append None? I did the following way:
    if node.left:
    q.append(node.left)
    if node.right:
    q.append(node.right)

  • @shreehari2589
    @shreehari2589 Pƙed rokem

    Freaking genius 😘

  • @samuel2318
    @samuel2318 Pƙed rokem

    clear explanation! I solve it by myself, but I still come to see any alternative to solve this question.

  • @wecankinetic
    @wecankinetic Pƙed 7 měsĂ­ci +1

    would love if these videos did more to explain how to come up with the solution instead of just describing the solution

  • @ketansharma6955
    @ketansharma6955 Pƙed rokem

    noice

  • @Goodday-nm7zp
    @Goodday-nm7zp Pƙed 9 měsĂ­ci

    I love this channel!!

  • @kirillzlobin7135
    @kirillzlobin7135 Pƙed 10 měsĂ­ci

    You are the legend maaaan

  • @aquapisces
    @aquapisces Pƙed 2 lety

    what if the node 9 also had children

  • @sumeetbisen9708
    @sumeetbisen9708 Pƙed 2 lety

    What will be the time complexity if I use recursion for this problem?
    like this:
    res = [ ]
    def bfs(node, level):
    if not node:
    return
    res[level].append(node.val)
    bfs(node.left, level+1)
    bfs(node.right, level+1)

  • @buttofthejoke
    @buttofthejoke Pƙed 6 měsĂ­ci +1

    Instead of adding level.append(node.val), can't we directly push it into the result.append(node.val)? since we're already pushing it in that order?

  • @rafaf8764
    @rafaf8764 Pƙed 7 měsĂ­ci

    LOVE U

  • @eddiej204
    @eddiej204 Pƙed rokem

  • @user-oc6ky2tk5o
    @user-oc6ky2tk5o Pƙed 2 lety

    had to add
    if level:
    res.append(level)
    for it to work on leetcode, not sure why this difference occured

  • @sanooosai
    @sanooosai Pƙed 3 měsĂ­ci

    thank you sir