Skip to content

Latest commit

 

History

History
239 lines (198 loc) · 7.66 KB

576.md

File metadata and controls

239 lines (198 loc) · 7.66 KB

【中规中矩】1698. 字符串的不同子字符串个数

四种解法,每种方法分别用C++和Python实现。共8个version代码。从简单的递归,到记忆化优化,再到两种dp代码实现。注释很详细,有疑问欢迎留言。

// Brute force recursion: TLE
class Solution1 {
public:
    int findPaths(int m, int n, int N, int i, int j) {
        return dfs(m, n, N, i, j);
    }
    
    int dfs(int m, int n, int N, int i, int j) {
        if (i < 0 || j < 0 || i >= m || j >= n) {
            return 1;
        }

        if (N == 0) {
            return 0; // after N step still within range
        }

        int res = 0;
        for (const auto& dir : dirs) {
            auto ni = i + dir[0];
            auto nj = j + dir[1];
            res += dfs(m, n, N - 1 , ni, nj);
        }

        return res;
    }

private:
    vector<vector<int>> dirs = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
};

// Memoization: AC
class Solution2 {
public:
    int findPaths(int m, int n, int N, int i, int j) {
        memo = vector<vector<vector<int>>> (m, vector<vector<int>>(n, vector<int>(N + 1, -1)));
        return dfs(m, n, N, i, j);
    }
    
    long dfs(int m, int n, int N, int i, int j) {
        if (i < 0 || j < 0 || i >= m || j >= n) {
            return 1;
        }

        if (memo[i][j][N] != -1) {
            return memo[i][j][N];
        }

        if (N == 0) {
            return 0; // after N step still within range
        }

        long res = 0;
        for (const auto& dir : dirs) {
            auto ni = i + dir[0];
            auto nj = j + dir[1];
            res += dfs(m, n, N - 1 , ni, nj);
            res %= MOD;
        }

        memo[i][j][N] = res;
        return memo[i][j][N];
    }

private:
    vector<vector<int>> dirs = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
    vector<vector<vector<int>>> memo;
    const int MOD = 1000000007;
};

// DP1: AC
class Solution3 {
public:
    int findPaths(int m, int n, int N, int i, int j) {
        vector<vector<vector<int>>> dp(m, vector<vector<int>>(n, vector<int>(N + 1, 0)));
        long res = 0;
        dp[i][j][0] = 1; // start
        for (int k = 1; k <= N; k++) {
            for (int i = 0; i < m; i++) {
                for (int j = 0; j < n; j++) {
                    for (const auto& dir : dirs) {
                        auto ni = i + dir[0];
                        auto nj = j + dir[1];
                        if (ni < 0 || nj < 0 || ni >= m || nj >= n) {
                            // out of board, accmulate the result
                            res = (res + dp[i][j][k - 1]) % MOD;
                        } else {
                            // within board, the total ways of arriving at pos (ni, nj)
                            // in k steps equals the total ways of arriving at pos (i, j)
                            // in (k - 1) step and then arriving at (ni, nj) from 4 dirs 
                            dp[ni][nj][k] = (dp[ni][nj][k] + dp[i][j][k - 1]) % MOD;
                        }
                        res %= MOD;
                    }
                }
            }
        }

            return res; 
    }

private:
    vector<vector<int>> dirs = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
    const int MOD = 1000000007;
};

// DP2: AC (think reverse, the problem is equivalent to starting from outside, in k steps
// how many ways to arrive at postion (r, c))
class Solution {
public:
    int findPaths(int m, int n, int K, int r, int c) {
        vector<vector<vector<long>>> dp(K + 1, vector<vector<long>>(m, vector<long>(n, 0)));
        long res = 0;
        for (int k = 1; k <= K; k++) {
            for (int i = 0; i < m; i++) {
                for (int j = 0; j < n; j++) {
                    long up = (i == 0 ? 1 : dp[k - 1][i - 1][j]);
                    long down = (i == m - 1 ? 1 : dp[k - 1][i + 1][j]);
                    long left = (j == 0 ? 1 : dp[k - 1][i][j - 1]);
                    long right = (j == n - 1 ? 1 : dp[k - 1][i][j + 1]);
                    dp[k][i][j] = (up + down + left + right) % MOD;
                }
            }
        }

            return dp[K][r][c]; 
    }

private:
    const int MOD = 1000000007;
};
#Brute force recursion: TLE
class Solution1(object):
    def findPaths(self, m, n, N, i, j):    
        def dfs(m, n, N, i, j):
            if (i < 0 or j < 0 or i >= m or j >= n):
                return 1

            if (N == 0):
                return 0   # after N step still within range

            res = 0
            dirs = [[-1, 0], [0, 1], [1, 0], [0, -1]]
            for dir in dirs:
                ni = i + dir[0]
                nj = j + dir[1]
                res += dfs(m, n, N - 1 , ni, nj);

            return res;
        
        return dfs(m, n, N, i, j)


#Memoization: AC
class Solution2(object):
    def findPaths(self, m, n, N, i, j):    
        MOD = 1000000007;
        memo = [[[-1] * (N + 1) for _ in range(n + 1)] for _ in range(m + 1)]
        def dfs(m, n, N, i, j):
            if (i < 0 or j < 0 or i >= m or j >= n):
                return 1

            if (N == 0):
                return 0   # after N step still within range

            if (memo[i][j][N] != -1):
                return memo[i][j][N]

            res = 0
            dirs = [[-1, 0], [0, 1], [1, 0], [0, -1]]
            for dir in dirs:
                ni = i + dir[0]
                nj = j + dir[1]
                res += dfs(m, n, N - 1 , ni, nj);

            memo[i][j][N] = res % MOD;
            return memo[i][j][N];
        
        return dfs(m, n, N, i, j)

# DP1: AC
class Solution3(object):
    def findPaths(self, m, n, N, i, j):
        dirs = [[-1, 0], [0, 1], [1, 0], [0, -1]]
        MOD = 1000000007;

        dp = [[[0] * (N + 1) for _ in range(n + 1)] for _ in range(m + 1)]
        res = 0
        dp[i][j][0] = 1 # start
        for k in range(1, N + 1):
            for i in range(0, m):
                for j in range(0, n):
                    for dir in dirs:
                        ni = i + dir[0]
                        nj = j + dir[1]
                        if (ni < 0 or nj < 0 or ni >= m or nj >= n):
                            # out of board, accmulate the result
                            res = (res + dp[i][j][k - 1]) % MOD
                        else:
                            # within board, the total ways of arriving at pos (ni, nj)
                            # in k steps equals the total ways of arriving at pos (i, j)
                            # in (k - 1) step and then arriving at (ni, nj) from 4 dirs 
                            dp[ni][nj][k] = (dp[ni][nj][k] + dp[i][j][k - 1]) % MOD
                        res %= MOD;
        return res; 

# DP2: AC (think reverse, the problem is equivalent to starting from outside, in k steps
# how many ways to arrive at postion (r, c))
class Solution(object):
    def findPaths(self, m, n, K, r, c):
        MOD = 1000000007;
        dp = [[[0] * (n) for _ in range(m + 1)] for _ in range(K + 2)]
        res = 0;
        for k in range(1, K + 1):
            for i in range(0, m):
                for j in range(0, n):
                    up = (1 if i == 0 else dp[k - 1][i - 1][j])
                    down = (1 if i == m - 1 else dp[k - 1][i + 1][j])
                    left = (1 if j == 0 else dp[k - 1][i][j - 1])
                    right = (1 if j == n - 1 else dp[k - 1][i][j + 1])
                    dp[k][i][j] = (up + down + left + right) % MOD

        return dp[K][r][c];

点我赞赏作者

github 题解

Image