自学内容网 自学内容网

【力扣-递归/搜索/回溯/动态规划】不同路径+组合总和{题解分享}


在这里插入图片描述

不同路径

不同路径

class Solution {
    int dfs(int i, int j, vector<vector<int>>& memo) {
        if (memo[i][j] != 0)
            return memo[i][j];

        if (i == 0 || j == 0)
            return 0;
        if (i == 1 && j == 1)
            return memo[i][j] = 1;

        memo[i][j] = dfs(i - 1, j, memo) + dfs(i, j - 1, memo);
        return memo[i][j];
    }

public:
    int uniquePaths(int m, int n) {
        // 解法一:数学/组合数
        // long long ans = 1;
        // // 第一次y=1 最后一次y=m-1
        // // 第一次x=n 最后一次x=n+m-2
        // for (int x = n, y = 1; y < m; ++x, ++y) {
        //     ans = ans * x / y;
        // }
        // return ans;

        // 解法二: 记忆化搜索
        vector<vector<int>> memo(m + 1, vector<int>(n + 1));
        return dfs(m, n, memo);

        // 解法三:动态规划
        // vector<vector<int>> dp(m + 1, vector<int>(n + 1));
        // dp[1][1] = 1;
        // for (int i = 1; i <= m; i++)
        //     for (int j = 1; j <= n; j++) {
        //         if (i == 1 && j == 1)
        //             continue;
        //         dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
        //     }
        // return dp[m][n];
    }
};

不同路径 II

class Solution {
public:
    int uniquePathsWithObstacles(vector<vector<int>>& ob) {
        int m = ob.size(), n = ob[0].size();
        vector<vector<int>> dp(m + 1, vector<int>(n + 1));
        dp[0][1] = 1;
        for (int i = 1; i <= m; i++)
            for (int j = 1; j <= n; j++)
                if (ob[i - 1][j - 1] == 0)
                    dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
        return dp[m][n];
    }
};

不同路径 III

class Solution {
    bool vis[21][21];
    int dx[4] = {1, -1, 0, 0};
    int dy[4] = {0, 0, 1, -1};
    int ret;
    int m, n, step;

public:
    int uniquePathsIII(vector<vector<int>>& grid) {
        m = grid.size(), n = grid[0].size();
        int bx = 0, by = 0;
        for (int i = 0; i < m; i++)
            for (int j = 0; j < n; j++)
                if (grid[i][j] == 0)
                    step++;
                else if (grid[i][j] == 1) {
                    bx = i;
                    by = j;
                }
        step += 2;
        vis[bx][by] = true;
        dfs(grid, bx, by, 1);
        return ret;
    }
    void dfs(vector<vector<int>>& grid, int i, int j, int count) {
        if (grid[i][j] == 2) {
            if (count == step) // 判断是否合法
                ret++;
            return;
        }
        for (int k = 0; k < 4; k++) {
            int x = i + dx[k], y = j + dy[k];
            if (x >= 0 && x < m && y >= 0 && y < n && !vis[x][y] &&
                grid[x][y] != -1) {
                vis[x][y] = true;
                dfs(grid, x, y, count + 1);
                vis[x][y] = false;
            }
        }
    }
};

组合总和

组合总和 【无重复数字+无限制选择次数】

class Solution {
    int aim;
    vector<int> path;
    vector<vector<int>> ret;

public:
    vector<vector<int>> combinationSum(vector<int>& nums, int target) {
        aim = target;
        dfs(nums, 0, 0);
        return ret;
    }
    void dfss(vector<int>& nums, int pos, int sum) {
        if (sum == aim) {
            ret.push_back(path);
            return;
        }
        if (sum > aim || pos == nums.size())
            return;

        for (int i = pos; i < nums.size(); i++) {
            path.push_back(nums[i]);
            dfss(nums, i, sum + nums[i]);
            path.pop_back();
        }
    }
    void dfs(vector<int>& nums, int pos, int sum) {
        if (sum == aim) {
            ret.push_back(path);
            return;
        }
        if (sum > aim || pos == nums.size())
            return;

        for (int k = 0; k * nums[pos] + sum <= aim; k++) {
            if (k != 0)
                path.push_back(nums[pos]);
            dfs(nums, pos + 1, sum + k * nums[pos]);
        }

        for (int k = 1; k * nums[pos] + sum <= aim; k++) {
            path.pop_back();
        }
    }
};

组合总和 II 【有重复数字+只能选择一次】

class Solution {
    vector<vector<int>> ans;
    vector<int> path;
    int n;
    int aim;

public:
    vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
        ranges::sort(candidates);
        n = candidates.size();
        aim = target;
        dfs(candidates, 0, 0);
        return ans;
    }
    void dfs(vector<int>& candidates, int pos, int sum) {
        if (sum == aim) {
            ans.push_back(path);
            return;
        }

        if (sum > aim || pos == n)
            return;

        for (int i = pos; i < n; i++) {
            if (i > pos && candidates[i] == candidates[i - 1])
                continue;

            path.push_back(candidates[i]);
            dfs(candidates, i + 1, sum + candidates[i]);
            path.pop_back();
        }
    }
};

组合总和 III【「在 9 个数中选择 k 个数」的组合枚举】

class Solution {
    vector<int> path;
    vector<vector<int>> ans;

    int x;
    int xSum;

public:
    void dfs(int cur, int n, int pathSum) {
        if (path.size() + (n - cur + 1) < x || path.size() > x)
            return;

        // accumulate(path.begin(), path.end(), 0) == xSum
        if (path.size() == x && pathSum == xSum) {
            ans.push_back(path);
            return;
        }
        path.push_back(cur);
        dfs(cur + 1, n, cur + pathSum);
        path.pop_back();

        dfs(cur + 1, n, pathSum);
    }

    vector<vector<int>> combinationSum3(int k, int n) {
        x = k;
        xSum = n;
        int pathSum = 0;
        dfs(1, 9, pathSum);
        return ans;
    }
};

组合总和 Ⅳ【无重复数字+爬楼梯】

class Solution {
    // dfs(i) 表示爬 i 个台阶的方案数
    int dfs(int i, vector<int>& nums, vector<int>& memo) {
        if (i == 0)
            return 1;

        int& res = memo[i]; // 注意这里是引用
        if (res != -1)
            return res;

        res = 0;
        for (int x : nums) {
            if (x <= i) {
                res += dfs(i - x, nums, memo);
            }
        }
        return res;
    }

public:
    int combinationSum4(vector<int>& nums, int target) {
        vector<int> memo(target + 1, -1);
        // return dfs(target, nums, memo);

        vector<unsigned> f(target + 1);
        f[0] = 1;
        for (int i = 1; i <= target; i++) {
            for (int x : nums) {
                if (x <= i)
                    f[i] += f[i - x];
            }
        }
        return f[target];
    }
};


原文地址:https://blog.csdn.net/LHRan_ran_/article/details/145239112

免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!