《剑指Offer——剪绳子,圆圈中最后剩下的数字》代码

Posted 穿迷彩服的鲨鱼

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《剑指Offer——剪绳子,圆圈中最后剩下的数字》代码相关的知识,希望对你有一定的参考价值。


前言

//==================================================================
// 《剑指Offer——剪绳子,圆圈中最后剩下的数字》代码
// =================================================================
// 题目:给你一根长度为n绳子,请把绳子剪成m段(m、n都是整数,n>1并且m≥1)。
// 每段的绳子的长度记为k[0]、k[1]、……、k[m]。k[0]k[1]…*k[m]可能的最大乘
// 积是多少?例如当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此
// 时得到最大的乘积18。
// =================================================================
// 题目:0, 1, …, n-1这n个数字排成一个圆圈,从数字0开始每次从这个圆圈里
// 删除第m个数字。求出这个圆圈里剩下的最后一个数字。
//==================================================================


一、示例

1.剪绳子

/*======================================================================================
给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),
每段绳子的长度记为 k[0],k[1]...k[m-1] 。请问 k[0]*k[1]*...*k[m-1] 可能的最大乘积是多少?
例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。

示例 1:

输入: 2
输出: 1
解释: 2 = 1 + 1, 1 × 1 = 1
示例 2:

输入: 10
输出: 36
解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36
===============================================================================*/

2.圆圈中最后剩下的数字

/*=========================================================
0,1,···,n-1这n个数字排成一个圆圈,从数字0开始,
每次从这个圆圈里删除第m个数字(删除后从下一个数字开始计数)。
求出这个圆圈里剩下的最后一个数字。
例如,0、1、2、3、4这5个数字组成一个圆圈,
从数字0开始每次删除第3个数字,则删除的前4个数字依次是2、0、4、1,
因此最后剩下的数字是3。

示例 1:
输入: n = 5, m = 3
输出: 3

示例 2:
输入: n = 10, m = 17
输出: 2
======================================================*/

二、代码解析

1.新建.cpp文件

代码如下(示例):

//==================================================================
// 《剑指Offer——剪绳子,圆圈中最后剩下的数字》代码
// =================================================================
// 题目:给你一根长度为n绳子,请把绳子剪成m段(m、n都是整数,n>1并且m≥1)。
// 每段的绳子的长度记为k[0]、k[1]、……、k[m]。k[0]*k[1]*…*k[m]可能的最大乘
// 积是多少?例如当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此
// 时得到最大的乘积18。
// =================================================================
// 题目:0, 1, …, n-1这n个数字排成一个圆圈,从数字0开始每次从这个圆圈里
// 删除第m个数字。求出这个圆圈里剩下的最后一个数字。
//==================================================================



#include <iostream>
#include<vector>
#include<list>
using namespace std;

/*======================================================================================
给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),
每段绳子的长度记为 k[0],k[1]...k[m-1] 。请问 k[0]*k[1]*...*k[m-1] 可能的最大乘积是多少?
例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。

示例 1:

输入: 2
输出: 1
解释: 2 = 1 + 1, 1 × 1 = 1
示例 2:

输入: 10
输出: 36
解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36
===============================================================================*/
/*====================动态规划====================*/
int cuttingRope(int n)
{
	if (n < 2)return 0;
	if (n == 2)return 1;
	if (n == 3)return 2;
	vector<int> products(n + 1, 0);

	products[0] = 0;
	products[1] = 1;
	products[2] = 2;
	products[3] = 3;

	int max = 0;
	for (int i = 4; i <= n; ++i)
	{
		max = 0;
		for (int j = 1; j <= i / 2; ++j)
		{
			int product = products[j] * products[i - j];
			if (max < product)
			{
				max = product;
			}
			products[i] = max;
		}
	}
	max = products[n];
	return max;
}
/*====================贪婪算法====================*/
int maxProductAfterCutting_solution2(int length)
{
	if (length < 2)
		return 0;
	if (length == 2)
		return 1;
	if (length == 3)
		return 2;

	// 尽可能多地减去长度为3的绳子段
	int timesOf3 = length / 3;

	// 当绳子最后剩下的长度为4的时候,不能再剪去长度为3的绳子段。
	// 此时更好的方法是把绳子剪成长度为2的两段,因为2*2 > 3*1。
	if (length - timesOf3 * 3 == 1)
		timesOf3 -= 1;

	int timesOf2 = (length - timesOf3 * 3) / 2;

	return (int)(pow(3, timesOf3)) * (int)(pow(2, timesOf2));
}

/*=========================================================
0,1,···,n-1这n个数字排成一个圆圈,从数字0开始,
每次从这个圆圈里删除第m个数字(删除后从下一个数字开始计数)。
求出这个圆圈里剩下的最后一个数字。
例如,0、1、2、3、4这5个数字组成一个圆圈,
从数字0开始每次删除第3个数字,则删除的前4个数字依次是2、0、4、1,
因此最后剩下的数字是3。

示例 1:
输入: n = 5, m = 3
输出: 3

示例 2:
输入: n = 10, m = 17
输出: 2
======================================================*/
/*====================list容器====================*/
int lastRemaining(int n, int m)
{
	if (n < 1 || m < 1)return -1;
	int i = 0;
	list<int> numbers;
	for (i = 0; i < n; ++i)
	{
		numbers.push_back(i);
	}
	list<int>::iterator current = numbers.begin();
	while (numbers.size() > 1)
	{
		for (int i = 1; i < m; ++i)
		{
			current++;
			if (current == numbers.end())
			{
				current = numbers.begin();
			}
		}
		list<int>::iterator next = ++current;
		if (next == numbers.end())
		{
			next = numbers.begin();
		}
		--current;
		numbers.erase(current);
		current = next;
	}
	return *(current);
}
/*====================从下到上循环====================*/
int LastRemaining_Solution2(unsigned int n, unsigned int m)
{
	if (n < 1 || m < 1)
		return -1;

	int last = 0;
	for (int i = 2; i <= n; i++)
		last = (last + m) % i;

	return last;
}
int main()
{
	cout << "剪绳子" << endl;
	cout << "动态规划--->" << cuttingRope(10) << endl;
	cout << "贪婪算法--->" << maxProductAfterCutting_solution2(10) << endl;
	cout << "圆圈中最后剩下的数字" << endl;
	cout << "list容器--->" << lastRemaining(10, 3) << endl;
	cout << "从下到上循环--->" << LastRemaining_Solution2(10, 3) << endl;
	return 0;
}

三,测试


以上是关于《剑指Offer——剪绳子,圆圈中最后剩下的数字》代码的主要内容,如果未能解决你的问题,请参考以下文章

[剑指offer]面试题45:圆圈中最后剩下的数字

剑指offer62圆圈中最后剩下的数字

剑指Offer对答如流系列 - 圆圈中最后剩下的数字

剑指Offer面试题62. 圆圈中最后剩下的数字

[LeetCode]剑指 Offer 62. 圆圈中最后剩下的数字

剑指 Offer 62. 圆圈中最后剩下的数字-约瑟夫环