《剑指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——剪绳子,圆圈中最后剩下的数字》代码的主要内容,如果未能解决你的问题,请参考以下文章