Convert an Array Into a 2D Array With Conditions

medium array hash table greedy

Problem

Given an integer array nums, build a 2D array that uses exactly the elements of nums, where every row contains distinct integers and the number of rows is minimal. Return any valid answer. Rows may differ in length.

The key observation: a value that appears k times must land in k different rows, so the minimum number of rows equals the maximum frequency of any value.

Inputnums = [1,3,4,1,2,3,1]
Output[[1,3,4,2],[1,3],[1]]
Value 1 appears 3 times, so at least 3 rows are needed; every row above has distinct integers.

def findMatrix(nums):
    rows = []           # the 2D result
    seen = {}           # value -> how many rows already hold it
    for v in nums:
        r = seen.get(v, 0)      # next free row for this value
        if r == len(rows):      # no row deep enough yet
            rows.append([])     # open a new row
        rows[r].append(v)       # place v on row r
        seen[v] = r + 1         # this value now occupies one more row
    return rows
function findMatrix(nums) {
  const rows = [];                 // the 2D result
  const seen = new Map();          // value -> how many rows already hold it
  for (const v of nums) {
    const r = seen.get(v) || 0;    // next free row for this value
    if (r === rows.length) {       // no row deep enough yet
      rows.push([]);               // open a new row
    }
    rows[r].push(v);               // place v on row r
    seen.set(v, r + 1);            // this value now occupies one more row
  }
  return rows;
}
List<List<Integer>> findMatrix(int[] nums) {
    List<List<Integer>> rows = new ArrayList<>();
    Map<Integer, Integer> seen = new HashMap<>();
    for (int v : nums) {
        int r = seen.getOrDefault(v, 0);   // next free row for this value
        if (r == rows.size()) {            // no row deep enough yet
            rows.add(new ArrayList<>());   // open a new row
        }
        rows.get(r).add(v);                // place v on row r
        seen.put(v, r + 1);                // value occupies one more row
    }
    return rows;
}
vector<vector<int>> findMatrix(vector<int>& nums) {
    vector<vector<int>> rows;
    unordered_map<int, int> seen;          // value -> rows already holding it
    for (int v : nums) {
        int r = seen[v];                  // next free row (default 0)
        if (r == (int)rows.size()) {      // no row deep enough yet
            rows.push_back({});           // open a new row
        }
        rows[r].push_back(v);             // place v on row r
        seen[v] = r + 1;                  // value occupies one more row
    }
    return rows;
}
Time: O(n) Space: O(n)