• 剑指offer--剪绳子,动态规划


    今日学了思路,待补充

    题目:

    将长度为n的绳子剪成若干段,并求各段长度乘积的最大值。

    思路:

     1、动态规划
        设f(n)代表长度为n的绳子剪成若干段的最大乘积,如果第一刀下去,第一段长度是i,那么剩下的就需要剪n-i,那么f(n)=max{f(i)f(n-i)}。而f(n)的最优解对应着f(i)和f(n-i)的最优解,假如f(i)不是最优解,那么其最优解和f(n-i)乘积肯定大于f(n)的最优解,和f(n)达到最优解矛盾,所以f(n)的最优解对应着f(i)和f(n-i)的最优解。首先,剪绳子是最优解问题,其次,大问题包含小问题,并且大问题的最优解包含着小问题的最优解,所以可以使用动态规划求解问题,并且从小到大求解,把小问题的最优解记录在数组中,求大问题最优解时就可以直接获取,避免重复计算。
        n<2时,由于每次至少减一次,所以返回0。n=2时,只能剪成两个1,那么返回1。n=3时,可以剪成3个1,或者1和2,那么最大乘积是2。当n>3时,就可以使用公式进行求解。
        f(4)=max{f(1)f(3), f(2)f(2)}
        f(5)=max{f(1)f(4), f(2)f(3)}
        ...
        f(n)=max{f(1)f(n-1), f(2)f(n-2), f(3)f(n-3), ..., f(i)(fn-i), ...}
        因为需要保证f(i)f(n-i)不重复,就需要保证i<=n/2,这是一个限制条件,求1~n/2范围内的乘积,得到最大值
     2、贪心算法
        n<2时,返回0;n=2时,返回1;n=3时,返回2
        根据数学计算,当n>=5时,2(n-2)>n,3(n-3)>n,这就是说,将绳子剪成2和(n-2)或者剪成3和(n-3)时,乘积大于不剪的乘积,因此需要把绳子剪成2或者3。并且3(n-3)>=2(n-2),也就是说,当n>=5时,应该剪尽量多的3,可以使最后的乘积最大。对于长度是n的绳子,我们可以剪出n/3个3,剩余长度是1或者2,如果余数是1,就可以把1和最后一个3合并成4,那么4剪出两个2得到的乘积是4,比1*3大,因此这种情况下,需要将3的个数减少1,变成两个2;如果余数是2,那么无需做修改。
        可以得到最大的乘积是:3^timesOf3 * 2^timesOf2
        相比动态规划,计算更简便,但是需要一定的数学技巧。
    原文:https://blog.csdn.net/upupday19/article/details/79315885

    动态规划+贪婪

    https://blog.csdn.net/upupday19/article/details/79315885

     1 public class Cut_string {
     2     public static void main(String[] args) {
     3         System.out.println(maxAfterCutting(8));
     4         }
     5     //需要O(n^2)的时间复杂度和O(n)的空间复杂度的动态规划思路
     6     public static int maxAfterCutting(int length) {
     7         if(length<2)
     8             return 0;
     9         if(length==2)
    10             return 1;
    11         if(length==3)
    12             return 2;
    13         //子问题的最优解存储在F数组中,数组中第i个元素表示将长度为i的绳子剪成若干段
    14         int [] f = new int[length+1];
    15         f[0]=0;
    16         f[1]=1;
    17         f[2]=2;
    18         f[3]=3;
    19         int result = 0;
    20         for(int i = 4;i<=length;++i) {
    21             int max = 0;
    22             for(int j = 1;j<=i/2;++j) {
    23                 int num = f[j]*f[i-j];
    24                 if(max<num)
    25                     max=num;
    26                 f[i] = max;
    27             }
    28         }
    29         result = f[length];
    30         return result;    
    31     }
    32 }

     有待继续学习。

  • 相关阅读:
    74.Maximal Rectangle(数组中的最大矩阵)
    73.Largest Rectangle in Histogram(最大矩形)
    72.Minimum Window Substring(最小子串窗口)
    71.Edit Distance(编辑距离)
    70.Trapping Rain Water(容水量)
    69.Daily Temperatures(日常气温)
    68.Palindromic Substrings(回文字符串的个数)
    67.Task Scheduler(任务规划)
    66.Subarray Sum Equals K(子数组和为K的个数)
    65.Longest Increasing Subsequence(最长增长子序列)
  • 原文地址:https://www.cnblogs.com/10081-AA/p/10828389.html
Copyright © 2020-2023  润新知