剑指offer——15剪绳子

题目描述

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

题解:

  边界要注意一下,因为题目要求一定要分成至少两段,故,当n=1 ->1*0;   n=2  -> 1*1;   n=3   ->   2*1

  两种方法进行求解

  

动态规划:

  首先定义函数(n)为把长度为n的绳子剪成若干段后各段长度乘积的最大值。在剪第一刀的时候,我们有n-1种可能的选择,也就是剪出来的第一段绳子的可能长度分别为1,2….n-1。因此f(n) = max(f(i) * f(n-i))。

   

 1 class Solution {
 2 public:
 3     int cutRope(int number) {
 4         if (number <= 1)return 0;
 5         if (number < 5)return (number / 2)*(number - number / 2);//因为至少要分为2段
 6         vector<int>dp(number + 1, 0);
 7         dp[0] = 0, dp[1] = 1, dp[2] = 2, dp[3] = 3;
 8         int maxN = 0;
 9         for (int i = 4; i <= number; ++i)
10         {
11             maxN = 0;
12             for (int j = 1; j <= i / 2; ++j)
13             {
14                 int temp = dp[j] * dp[i - j];
15                 maxN = maxN > temp ? maxN : temp;
16                 dp[i] = maxN;
17             }
18         }
19         return dp[number];
20     }
21 };

贪婪算法:

  如果我们按照如下的策略来剪绳子,则得到的各段绳子的长度的乘积将最大:当n≥5时,我们尽可能多地剪长度为3的绳子;当剩下的绳子长度为4时,把绳子剪成两段长度为2的绳子。

  为什么要剪成3,这是个数学证明,详细请看书

  

 1 class Solution {
 2 public:
 3     int cutRope(int number) {
 4         if (number <= 1)return 0;
 5         if (number < 5)return (number / 2)*(number - number / 2);//因为至少要分为2段
 6         int n3 = number / 3;//3的个数
 7         if (number % 3 == 1)//最后剪的一段为4时,不要剪成3-1,要剪成2-2
 8             n3--;
 9         int n2 = (number - 3 * n3) / 2;//2的个数
10         return pow(3, n3)*pow(2, n2);
11     }
12 };

  

原文地址:https://www.cnblogs.com/zzw1024/p/11656418.html

时间: 2024-10-10 03:29:13

剑指offer——15剪绳子的相关文章

剑指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. def cutRopeDP(length): """ 在剪绳子这个题目中,由于必须要剪一刀,因此会导致当所给的绳子长度是小于4的时候,剪完之后的长度 小于剪之前的长度.但

【剑指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. 动态规划 总是从解决最小问题开始,并把已经解决的子问题的最优解存储下来(一维或二维数组),并把子问题的最优解组合起来逐步解决大的问题. 动态规划的特点: 问题的目标是,求一个问题的最优解:问题的目标是求

[剑指Offer] 15.反转链表

1 /* 2 struct ListNode { 3 int val; 4 struct ListNode *next; 5 ListNode(int x) : 6 val(x), next(NULL) { 7 } 8 };*/ 9 class Solution { 10 public: 11 ListNode* ReverseList(ListNode* pHead) { 12 ListNode* p = pHead; 13 ListNode* q = NULL; 14 ListNode* r

剑指offer (15) 链表倒数第K个结点

题目: 输入一个链表,输出该链表中倒数第k个结点 (注意:我们将链表最末一个结点记为 倒数第1个结点,也就是k从1开始计数) 解题分析: 方法一:遍历链表两次,第一次统计链表结点个数,第二次遍历就可以找到倒数第K个结点 方法二:遍历链表一次 我们使用两个指针,第一个指针从链表的头指针开始遍历向前走k-1步,第二个指针一直指向链表开头并保持不动 从第k步开始,两个指针同时向前走,这时 两个指针之间的距离一直是k-1 当第一个指针到达链表尾结点时,第二个指针指向链表倒数第k个结点 1 ListNod

剑指offer 15:链表的倒数第k个节点

题目描述 输入一个链表,输出该链表中倒数第k个结点. 解题思路 使用快慢指针法,让快指针先走k步,然后再让慢指针开始走,当快指针到达链表尾部时,慢指针刚好到达倒数第k个节点. C++代码实现: /* struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) { } };*/ class Solution { public: ListNode* FindKthToTail(ListN

剑指offer(15)

题目: 定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1)). 书中的思路: 按照这个思路我们很容易写出以下代码: import java.util.Stack; public class Solution { Stack stack = new Stack(); Stack assistStack = new Stack(); public void push(int node) { stack.push(node); if(assistStac

剑指OFFER 剪绳子

剑指OFFER 剪绳子 class Solution { public: int cutRope(int number) { //最少要剪一次,所以前面的dp数据有点特别 if(number == 1)return 1; if(number == 2)return 1; if(number == 3)return 2; vector<int> dp; dp.resize(number + 1); //这里是不需要再剪的数据,这里可能会多余一两个数据,但是没有关系,都写上 dp[0]=0; dp

剑指Offer系列之题11~题15

目录 11.矩形覆盖 12.二进制中1的个数 13. 数值的整数次方 14.调整数组顺序使奇数位于偶数前面 15.链表中倒数第k个结点 11.矩形覆盖 我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形.请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法? 比如n=3时,2*3的矩形块有3种覆盖方法: 斐波那契数列的应用 第一次竖着放一块类比为走一步,第一次横着放两块类比为走两步 代码与上面的斐波那契数列类题目类似,此处不再赘述:剑指Offer系列之题6~题10. 12.

剑指offer 面试14题

面试14题: 题目:剪绳子 题:给你一根长度为n的绳子,请把绳子剪成m段(m,n都是整数,且n>1,m>1),每段绳子的长度记为k[0],k[1],k[2],...,k[m].请问k[0]*k[1]*...*k[m]可能的最大乘积是多少?例如,当绳子的长度为8时,我们把它剪成长度分别为2,3,3的三段,此时得到的最大乘积为18. 解题思路:基于动态规划和贪婪算法,详见剑指offer P96 解题代码: # -*- coding:utf-8 -*- class Solution: def Max