the tree row here means the level order traverse.
public List largestValues(TreeNode root)

of course we can still use the level order traverse and after we get the whole list, we get the max.
but in the mean time, we can also get the largest by maintaining the largest for each level.

class Solution {
    public List<Integer> largestValues(TreeNode root) {
        List<Integer> avg = new ArrayList<>();
        if (root == null) return avg;
        Queue<TreeNode> queue = new LinkedList<>();
        
        TreeNode cur = root;
        queue.offer(cur);
        while (!queue.isEmpty()) {
            int size = queue.size();
            int max = Integer.MIN_VALUE;
            for (int i = 0; i < size; i++) {
                cur = queue.poll();
                max = Math.max(max, cur.val);
                if (cur.left != null) queue.offer(cur.left);
                if (cur.right != null) queue.offer(cur.right);
            }
            avg.add(max);
        }
        return avg;
    }
}