552. Student Attendance Record II

/**
 * 552. Student Attendance Record II
 * https://leetcode.com/problems/student-attendance-record-ii/
 * An attendance record for a student can be represented as a string where each
character signifies whether the student was absent, late, or present on that
day.
 * The record only contains the following three characters:
'A': Absent.
'L': Late.
'P': Present.
Any student is eligible for an attendance award if they meet both of the
following criteria:
1. The student was absent ('A') for strictly fewer than 2 days total.
2. The student was never late ('L') for 3 or more consecutive days.
Given an integer n, return the number of possible attendance records of length n
that make a student eligible for an attendance award. The answer may be very
large, so return it modulo 10^9 + 7.

Example 1:
Input: n = 2
Output: 8
Explanation: There are 8 records with length 2 that are eligible for an award:
"PP", "AP", "PA", "LP", "PL", "AL", "LA", "LL"
Only "AA" is not eligible because there are 2 absences (there need to be fewer
than 2).

Example 2:
Input: n = 1
Output: 3

Example 3:
Input: n = 10101
Output: 183236316

Constraints:
1 <= n <= 10^5
*/

/**
 * Solution: DFS + Memorizaion, use unordered_map for cache will LTE, pass all test by cache by vector; 
 * Time complexity: O(3n)
 * Space complexity: O(n)
 */
#include <iostream>
#include <string>
#include <unordered_map>
#include <vector>
using namespace std;

class Solution {
 private:
  vector<vector<vector<int>>> cache;
  // unordered_map<string, int> cache;

 public:
  const static int MOD = 1e9 + 7;

  /*string getKey(int current_level, int absent_count, int late_count) {
    return std::to_string(current_level) + "," + std::to_string(absent_count) +
           "," + std::to_string(late_count);
  }*/

  int checkRecord(int n) {
    initCache(n);
    int result = dfs(0, n, 0, 0);
    return result;
  }

/**
 * init cache: HEIGHT, WIDTH, DEPTH;
 * HEIGHT: represent two triteria;
 * WIDTH: represent 3 chars: A,L,P;
 * DEPTH: for n;
 * 
*/
  void initCache(int n) {
    int HEIGHT = 2, WIDTH = 3, DEPTH = n;
    cache.resize(HEIGHT);
    for (int i = 0; i < HEIGHT; i++) {
      cache[i].resize(WIDTH);
      for (int j = 0; j < WIDTH; j++) {
        cache[i][j].resize(DEPTH);
      }
    }
    for (int i = 0; i < HEIGHT; i++) {
      cache[i].resize(WIDTH);
      for (int j = 0; j < WIDTH; j++) {
        for (int k = 0; k < DEPTH; k++) {
          cache[i][j][k] = -1;
        }
      }
    }
  }

  int dfs(int current_level, int n, int absent_count, int late_count) {
    if (absent_count == 2 || late_count == 3) {
      return 0;
    }
    if (current_level == n) {
      return 1;
    }
    // LTE by unordered_map
    /*string key = getKey(current_level, absent_count, late_count);
    if (cache.find(key) != cache.end()) {
      return cache[key];
    }*/

    if (cache[absent_count][late_count][current_level] != -1) {
      return cache[absent_count][late_count][current_level];
    }
    int current_result = 0;
    // add another absent count
    current_result += dfs(current_level + 1, n, absent_count + 1, 0);
    current_result %= MOD;
    // add another late count
    current_result += dfs(current_level + 1, n, absent_count, late_count + 1);
    current_result %= MOD;
    // add another present count
    current_result += dfs(current_level + 1, n, absent_count, 0);
    current_result %= MOD;
    // cache[key] = current_result;
    cache[absent_count][late_count][current_level] = current_result;
    return current_result;
  }
};

 

posted @ 2023-01-24 15:26  johnny_zhao  阅读(14)  评论(0编辑  收藏  举报