剑指 Offer(第2版)面试题 60:n 个骰子的点数

剑指 Offer(第2版)面试题 60:n 个骰子的点数

  • 剑指 Offer(第2版)面试题 60:n 个骰子的点数
    • 解法 1:递归
    • 解法 2:动态规划

剑指 Offer(第2版)面试题 60:n 个骰子的点数

题目来源:80. 骰子的点数

解法 1:递归

这样做会超时。

代码:

class Solution
{
public:
	vector<int> numberOfDice(int n)
	{
		vector<int> ans;
		for (int i = n; i <= 6 * n; i++)
			ans.push_back(dfs(n, i));
		return ans;
	}
	// 辅函数 - 递归计算 n 个骰子丢出 point 点数的方案数
	int dfs(int n, int point)
	{
		if (n < 0 || point < 0)
			return 0;
		if (point == 0)
			return n == 0;
		int count = 0;
		for (int i = 1; i <= 6; i++)
			count += dfs(n - 1, point - i);
		return count;
	}
};

复杂度分析:

时间复杂度:O(n!),其中 n 是骰子的个数。

空间复杂度:O(n),其中 n 是骰子的个数。

解法 2:动态规划

设 dp[i][j] 为丢 i 个骰子掷出 j 点的方案数。

初始化:dp[1][j] = 1,1<=j<=6。

代码:

class Solution
{
public:
	vector<int> numberOfDice(int n)
	{
		if (n == 0)
			return {};
		// dp[i][j] 为丢 i 个骰子掷出 j 点的方案数
		vector<vector<int>> dp(n + 1, vector<int>(6 * n + 1, 0));
		// 初始化
		for (int j = 1; j <= 6; j++)
			dp[1][j] = 1;
		// 状态转移
		for (int i = 2; i <= n; i++)
			for (int j = i; j <= 6 * i; j++)
			{
			    // 状态转移方程
			    for (int k = 1; k <= 6; k++)
					if (j - k >= 0)
						dp[i][j] += dp[i - 1][j - k];
			}
		vector<int> ans;
		for (int i = n; i <= 6 * n; i++)
			ans.push_back(dp[n][i]);
		return ans;
	}
};

复杂度分析:

时间复杂度:O(n2),其中 n 是骰子的个数。

空间复杂度:O(n2),其中 n 是骰子的个数。动态规划数组的空间开销是 O(n) * O(6n) = O(6n2)。

空间优化:

由于我们只需要用到最后一次的结果,因此为了节省空间可以使用滚动数组,将二维 dp 数组变为一维。

代码:

class Solution
{
public:
	vector<int> numberOfDice(int n)
	{
	    if (n == 0)
	        return {};
		vector<int> dp(6 * n + 1, 0);
		// 初始化
		for (int i = 1; i <= 6; i++)
			dp[i] = 1;
		// 状态转移
		for (int i = 2; i <= n; i++)
		{
			for (int j = 6 * i; j >= 0; j--)
			{
				dp[j] = 0;
				for (int k = 6; k >= 1; k--)
				{ 
				    // 最后一个骰子可以扔1-6点
					if (j - k >= 0)
					    dp[j] += dp[j - k];
				}
			}
		}
		vector<int> res(dp.begin() + n, dp.end()); // 扔n个骰子的和为[n, 6*n]
		return res;
	}
};

复杂度分析:

时间复杂度:O(n2),其中 n 是骰子的个数。

空间复杂度:O(n),其中 n 是骰子的个数。动态规划数组的空间开销是 O(6 * n + 1)。

你可能感兴趣的:(剑指,Offer,C++,剑指Offer,数据结构与算法,动态规划,递归)