<p>Given a 2D integer array <code>nums</code>, return <em>all elements of </em><code>nums</code><em> in diagonal order as shown in the below images</em>.</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<img alt="" src="https://assets.leetcode.com/uploads/2020/04/08/sample_1_1784.png" style="width: 158px; height: 143px;" />
<pre>
<strong>Input:</strong> nums = [[1,2,3],[4,5,6],[7,8,9]]
<strong>Output:</strong> [1,4,2,7,5,3,8,6,9]
</pre>

<p><strong class="example">Example 2:</strong></p>
<img alt="" src="https://assets.leetcode.com/uploads/2020/04/08/sample_2_1784.png" style="width: 230px; height: 177px;" />
<pre>
<strong>Input:</strong> nums = [[1,2,3,4,5],[6,7],[8],[9,10,11],[12,13,14,15,16]]
<strong>Output:</strong> [1,6,2,8,7,3,9,4,12,10,5,13,11,14,15,16]
</pre>

<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li><code>1 &lt;= nums.length &lt;= 10<sup>5</sup></code></li>
	<li><code>1 &lt;= nums[i].length &lt;= 10<sup>5</sup></code></li>
	<li><code>1 &lt;= sum(nums[i].length) &lt;= 10<sup>5</sup></code></li>
	<li><code>1 &lt;= nums[i][j] &lt;= 10<sup>5</sup></code></li>
</ul>

class Solution:
    def findDiagonalOrder(self, nums: List[List[int]]) -> List[int]:
        visited = set()
        
        res = []
        
        queue = deque([(0,0)])
        
        while queue:
            temp = []
            for i,j in list(queue):
                queue.popleft()
                if (i,j) not in visited and i < len(nums) and j < len(nums[i]):
                    visited.add((i,j))
                    temp.append(nums[i][j])
                    queue.append((i+1, j))
                    queue.append((i, j+1))
            
            res.append(temp)
            
        
        # flatten list
        
        ans = []
        
        for temp in res:
            ans += temp
        
        return ans
    
    # just bfs
    def findDiagonalOrder(self, nums: List[List[int]]) -> List[int]:
        q = deque([(0,0)])
        res = []
        visited = set([(0,0)])
        dirs = [(1,0),(0,1)] # BOTTOM RIGHT THEN RIGHT
        while q:
            i,j = q.popleft()
            v = nums[i][j]
            #visited.add((i,j))
            res.append(v)
            for x,y in dirs:
                ii,jj = i+x,j+y
                if (ii,jj) not in visited and ii < len(nums) and jj < len(nums[ii]):
                    visited.add((ii,jj))
                    q.append((ii,jj))
        return res
    
    # another way...
    def findDiagonalOrder(self, nums: List[List[int]]) -> List[int]:
        q = deque([(0,0)])
        res = []
        visited = set()
        dirs = [(1,0),(0,1)] # BOTTOM RIGHT THEN RIGHT
        while q:
            i,j = q.popleft()
            if (i,j) in visited: continue
            if not (i < len(nums) and j < len(nums[i])): continue
            v = nums[i][j]
            visited.add((i,j))
            res.append(v)
            for x,y in dirs:
                ii,jj = i+x,j+y
                q.append((ii,jj))
        return res
            
        # use map, then flatten. diagonals are id'd by their sum of row+col.
    def findDiagonalOrder(self, nums: List[List[int]]) -> List[int]:
        idx = defaultdict(list)
        for i in range(len(nums)):
            for j in range(len(nums[i])):
                idx[i+j].append(nums[i][j])
        
        # reversed order
        res = []
        for i in sorted(idx):
            res.append(idx[i][::-1])
            
        def flatten(res):
            ans = []
            for l in res:
                for a in l:
                    ans.append(a)
            return ans
                
        return flatten(res)
            
        
        
            
            
            
    
        
        
                
48026