《剑指Offer——丑数,n个骰子的点数》代码

Posted 穿迷彩服的鲨鱼

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《剑指Offer——丑数,n个骰子的点数》代码相关的知识,希望对你有一定的参考价值。


前言

//==================================================================
// 《剑指Offer——丑数,n个骰子的点数》代码
// 题目:我们把只包含因子2、3和5的数称作丑数(Ugly Number)。求按从小到
// 大的顺序的第1500个丑数。例如6、8都是丑数,但14不是,因为它包含因子7。
// 习惯上我们把1当做第一个丑数。
// =================================================================
// 题目:把n个骰子扔在地上,所有骰子朝上一面的点数之和为s。输入n,打印出s
// 的所有可能的值出现的概率。
//==================================================================


一、示例

1.丑数

/*=======================================================
我们把只包含质因子 2、3 和 5 的数称作丑数(Ugly Number)。
求按从小到大的顺序的第 n 个丑数。

示例:
输入: n = 10
输出: 12
解释: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 是前 10 个丑数。
========================================================*/

2.n个骰子的点数

/*===============================================================================================
把n个骰子扔在地上,所有骰子朝上一面的点数之和为s。
输入n,打印出s的所有可能的值出现的概率。
你需要用一个浮点数数组返回答案,其中第 i 个元素代表这 n
个骰子所能掷出的点数集合中第 i 小的那个的概率。

示例 1:
输入: 1
输出: [0.16667,0.16667,0.16667,0.16667,0.16667,0.16667]

示例 2:
输入: 2
输出: [0.02778,0.05556,0.08333,0.11111,0.13889,0.16667,0.13889,0.11111,0.08333,0.05556,0.02778]
=================================================================================================*/

二、代码解析

1.新建.cpp文件

代码如下(示例):

//==================================================================
// 《剑指Offer——丑数,n个骰子的点数》代码
// 题目:我们把只包含因子2、3和5的数称作丑数(Ugly Number)。求按从小到
// 大的顺序的第1500个丑数。例如6、8都是丑数,但14不是,因为它包含因子7。
// 习惯上我们把1当做第一个丑数。
// =================================================================
// 题目:把n个骰子扔在地上,所有骰子朝上一面的点数之和为s。输入n,打印出s
// 的所有可能的值出现的概率。
//==================================================================



#include <iostream>
#include<vector>
#include<unordered_set>
#include <queue>
using namespace std;

/*=======================================================
我们把只包含质因子 2、3 和 5 的数称作丑数(Ugly Number)。
求按从小到大的顺序的第 n 个丑数。

示例:
输入: n = 10
输出: 12
解释: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 是前 10 个丑数。
========================================================*/

bool IsUgly(int number)
{
	while (number % 2 == 0)
	{
		number /= 2;
	}
	while (number % 3 == 0)
	{
		number /= 3;
	}
	while (number % 5 == 0)
	{
		number /= 5;
	}
	return (number == 1) ? true : false;
}
/*====================暴力解法====================*/
int nthUglyNumber1(int n)
{
	if (n < 0)
	{
		return 0;
	}
	int number = 0;
	int uglyFound = 0;
	while (uglyFound < n)
	{
		++number;
		if (IsUgly(number))
		{
			++uglyFound;
		}
	}
	return number;
}
/*====================动态规划====================*/
int nthUglyNumber2(int n)
{
	vector<int> dp(n + 1);
	dp[1] = 1;
	int p2 = 1, p3 = 1, p5 = 1;
	for (int i = 2; i <= n; ++i)
	{
		int num2 = dp[p2] * 2, num3 = dp[p3] * 3, num5 = dp[p5] * 5;
		dp[i] = min(min(num2, num3), num5);
		if (dp[i] == num2)
		{
			p2++;
		}
		if (dp[i] == num3)
		{
			p3++;
		}
		if (dp[i] == num5)
		{
			p5++;
		}
	}
	return dp[n];
}

/*===============================================================================================
把n个骰子扔在地上,所有骰子朝上一面的点数之和为s。
输入n,打印出s的所有可能的值出现的概率。
你需要用一个浮点数数组返回答案,其中第 i 个元素代表这 n
个骰子所能掷出的点数集合中第 i 小的那个的概率。

示例 1:
输入: 1
输出: [0.16667,0.16667,0.16667,0.16667,0.16667,0.16667]

示例 2:
输入: 2
输出: [0.02778,0.05556,0.08333,0.11111,0.13889,0.16667,0.13889,0.11111,0.08333,0.05556,0.02778]
=================================================================================================*/
vector<double> dicesProbability(int n)
{
	vector<double> dp(6, 1.0 / 6.0);
	for (int i = 2; i <= n; i++)
	{
		vector<double> tmp(5 * i + 1, 0);
		for (int j = 0; j < dp.size(); ++j)
		{
			for (int k = 0; k < 6; ++k)
			{
				tmp[j + k] += dp[j] / 6.0;
			}
		}
		dp = tmp;
	}
	return dp;
}
int main()
{
	cout << "/*====================丑数====================*/" << endl;
	cout << "暴力解法------>" << nthUglyNumber1(150) << endl;
	cout << "动态规划------>" << nthUglyNumber2(150) << endl;
	cout << "/*====================n个骰子的点数====================*/" << endl;
	vector<double> result1 = dicesProbability(1);
	vector<double> result2 = dicesProbability(2);
	cout << "1个" << endl;
	for (int i = 0; i < result1.size(); ++i)
	{
		cout << result1[i] << " ";
	}
	cout <<endl<< "2个" << endl;
	for (int i = 0; i < result2.size(); ++i)
	{
		cout << result2[i] << " ";
	}
	return 0;
}

三,测试


以上是关于《剑指Offer——丑数,n个骰子的点数》代码的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode(剑指 Offer)- 60. n个骰子的点数

LeetCode(剑指 Offer)- 60. n个骰子的点数

剑指 Offer 60. n个骰子的点数 --- 动态规划

剑指offer——第二十九天(动态规划“困难”)

剑指offer-求n个骰子所有点数出现的概率,求二叉树的深度和判断是否是AVL树

剑指Offer对答如流系列 - n个骰子的点数