umma.dev

Algorithms + Data Structures: Recursion

Recursion is what recursion says it is on the tin.

What is Recursion?

According to Google…

The repeated application of a recursive procedure or definition.

Example

const getNthFib = (n) => {
  if (n === 1) return 0;
  if (n === 2) return 1;
  return getNthFib(n - 1) + getNthFib(n - 2);
};

getNthFib(2);

Problem Sets

Easy

Product Sum

Write a function that takes in a “special” array and returns its product sum. A “special” array is a non-empty array that contains either integers or other “special” arrays. The product sum of a “special” array is the sum of its elements, where “special” arrays inside it are summed themselves and then multiplied by their level of depth. The depth of a “special” array is how far nested it is. For instance, the depth of [] is 1 and [[]] is two, and so on.

Sample Input

array = [5, 2, [7, -1], 3, [6, [-13, 8], 4]]

Sample Output

12 // 5 + 2 + 2 * (7 - 1) + 3 + 2 * (6 + 3 * (-13 + 8) + 4)

Code Given

function productSum(array) {}

Answer

function productSum(array, depth = 1) {
  const sum = array.reduce((a, b) => {
    if (Array.isArray(b)) return a + productsum(b, depth + 1);
    return a + b;
  }, 0);
  return sum * depth;
}

Medium

Permutations

Write a function that takes in an array of unique integers and returns an array of all permutations of those integers in no particular order.

If the input is empty, the function should return an empty array.

Sample Input

array = [1, 2, 3]

Sample Output

[[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]

Code Given

function getPermutations(array) {}

Answer

function getPermutations(array) {
  const permutations = [];
  permutationsHelper(0, array, permutations);
  return permutations;
}

function permutationsHelper(i, array, permutations) {
  if (i === array.length - 1) {
    permutations.push(array.slice());
  } else {
    for (let j = i; j < array.length; j++) {
      swap(i, j, array);
      permutationsHelper(i + 1, array, permutations);
      swap(i, j, array);
    }
  }
}

function swap(i, j, array) {
  const temp = array[i];
  array[i] = array[j];
  array[j] = temp;
}

Hard

Solve Sudoku

You’re given a two-dimensional array that represents a 9x9 partially filled Sudoku board. Write a function that returns the solved Sudoku board.

Sample Input

board =
[
  [7, 8, 0, 4, 0, 0, 1, 2, 0],
  [6, 0, 0, 0, 7, 5, 0, 0, 9],
  [0, 0, 0, 6, 0, 1, 0, 8, 8],
  [0, 0, 7, 0, 4, 0, 2, 6, 0],
  [0, 0, 1, 0, 5, 0, 9, 3, 0],
  [9, 0, 4, 0, 6, 0, 0, 0, 5],
  [0, 7, 0, 3, 0, 0, 0, 1, 2],
  [1, 2, 0, 0, 0, 7, 4, 0, 0],
  [0, 4, 9, 2, 0, 6, 0, 0, 7]
]

Sample Output

[
  [7, 8, 5, 4, 3, 9, 1, 2, 6],
  [6, 1, 2, 8, 7, 5, 3, 4, 9],
  [4, 9, 3, 6, 2, 1, 5, 7, 8],
  [8, 5, 7, 9, 4, 3, 2, 6, 1],
  [2, 6, 1, 7, 5, 8, 9, 3, 4],
  [9, 3, 4, 1, 6, 2, 7, 8, 5],
  [5, 7, 8, 3, 9, 4, 6, 1, 2],
  [1, 2, 6, 5, 8, 7, 4, 9, 3],
  [3, 4, 9, 2, 1, 6, 8, 5, 7],
]

Code Given

function solveSudoku(board) {
  return [];
}

Answer

function solveSudoku(board) {
  solvePartialSudoku(0, 0, board);
  return board;
}

function solvePartialSudoku(row, col, board) {
  let currentRow = row;
  let currentCol = col;

  if (currentCol === board[currentRow].length) {
    currentRow++;
    currentcol = 0;
    if (currentRow === board.length) return true;
  }

  if (board[currentRow][currentCol] === 0)
    return tryDigitsAtPosition(currentRow, currentCol, board);

  return solvePartialSudoku(currentRow, currentCol + 1, board);
}

function tryDigitsAtPosition(row, col, board) {
  for (let digit = 1; digit < 10; digit++) {
    if (isValidAtPosition(digit, row, col, board)) {
      board[row][col] = digit;
      if (solvePartialSudoku(row, col + 1, board)) return true;
    }
  }
  board[row][col] = 0;
  return false;
}

function isValidAtPosition(value, row, col, board) {
  const rowIsValid = !board[row].includes(value);
  const colIsValid = !board.map((r) => r[col]).includes(value);

  if (!rowIsValid || !colIsValid) return false;

  const subgridRowStart = Math.floor(row / 3) * 3;
  const subgridColStart = Math.floor(col / 3) * 3;

  for (let rowIndex = 0; rowIndex < 3; rowIndex++) {
    for (let colIndex = 0; colIndex < 3; colIndex++) {
      const rowToCheck = subgridRowStart + rowIndex;
      const colToCheck = subgridColStart + colIndex;
      const existingValue = board[rowToCheck][colToCheck];

      if (existingValue === value) return false;
    }
  }
  return true;
}