LeetCode Solutions

935. Knight Dialer

Time: $O(n)$

Space: $O(n)$

			

class Solution {
 public:
  int knightDialer(int n) {
    constexpr int kMod = 1'000'000'007;
    const vector<pair<int, int>> dirs = {{-2, 1}, {-1, 2}, {1, 2},   {2, 1},
                                         {2, -1}, {1, -2}, {-1, -2}, {-2, -1}};

    // dp[i][j] := # of ways to stand on (i, j)
    vector<vector<int>> dp(4, vector<int>(3, 1));
    dp[3][0] = dp[3][2] = 0;

    for (int k = 0; k < n - 1; ++k) {
      vector<vector<int>> newDp(4, vector<int>(3));
      for (int i = 0; i < 4; ++i)
        for (int j = 0; j < 3; ++j) {
          if (isNotNumericCell(i, j))
            continue;
          for (const auto& [dx, dy] : dirs) {
            const int x = i + dx;
            const int y = j + dy;
            if (x < 0 || x >= 4 || y < 0 || y >= 3)
              continue;
            if (isNotNumericCell(x, y))
              continue;
            newDp[i][j] = (newDp[i][j] + dp[x][y]) % kMod;
          }
        }
      dp = move(newDp);
    }

    int ans = 0;

    for (const vector<int>& row : dp)
      for (const int a : row)
        ans = (ans + a) % kMod;

    return ans;
  }

 private:
  bool isNotNumericCell(int i, int j) {
    return i == 3 && (j == 0 || j == 2);
  }
};
			

class Solution {
  public int knightDialer(int n) {
    final int kMod = 1_000_000_007;
    final int[][] dirs = {{-2, 1}, {-1, 2}, {1, 2}, {2, 1}, {2, -1}, {1, -2}, {-1, -2}, {-2, -1}};
    // dp[i][j] := # of ways to stand on (i, j)
    int[][] dp = new int[4][3];
    Arrays.stream(dp).forEach(row -> Arrays.fill(row, 1));
    dp[3][0] = dp[3][2] = 0;

    for (int k = 0; k < n - 1; ++k) {
      int[][] newDp = new int[4][3];
      for (int i = 0; i < 4; ++i)
        for (int j = 0; j < 3; ++j) {
          if (isNotNumericCell(i, j))
            continue;
          for (int[] dir : dirs) {
            final int x = i + dir[0];
            final int y = j + dir[1];
            if (x < 0 || x >= 4 || y < 0 || y >= 3)
              continue;
            if (isNotNumericCell(x, y))
              continue;
            newDp[i][j] = (newDp[i][j] + dp[x][y]) % kMod;
          }
        }
      dp = newDp;
    }

    int ans = 0;

    for (int[] row : dp)
      for (final int a : row)
        ans = (ans + a) % kMod;

    return ans;
  }

  private boolean isNotNumericCell(int i, int j) {
    return i == 3 && (j == 0 || j == 2);
  }
}
			

class Solution:
  def knightDialer(self, n: int) -> int:
    kMod = 1_000_000_007
    dirs = [(-2, 1), (-1, 2), (1, 2), (2, 1),
            (2, -1), (1, -2), (-1, -2), (-2, -1)]

    # dp[i][j] := # Of ways stand on (i, j)
    dp = [[1] * 3 for _ in range(4)]
    dp[3][0] = dp[3][2] = 0

    for _ in range(n - 1):
      newDp = [[0] * 3 for _ in range(4)]
      for i in range(4):
        for j in range(3):
          if (i, j) in ((3, 0), (3, 2)):
            continue
          for dx, dy in dirs:
            x = i + dx
            y = j + dy
            if x < 0 or x >= 4 or y < 0 or y >= 3:
              continue
            if (x, y) in ((3, 0), (3, 2)):
              continue
            newDp[x][y] = (newDp[x][y] + dp[i][j]) % kMod
      dp = newDp

    return sum(map(sum, dp)) % kMod