剪绳子 整数划分 动态规划与贪婪 剑指offer编程题整理 leetcode每日算法题

动态规划

独立子问题?最优解?贪心?

1大问题可以分解成小问题,大问题的最优解包括小问题的最优解,那么可以求出小问题的最优解,存到数组中,在求大问题最优解时就可以直接从数组中获取,最终获得最优解。

2动态规划:如果要求一个问题的最优解,而且该问题能分成若干个子问题,整体问题的最优解依赖于子问题的最优解,可以考虑用动态规划解决。动态规划一般是自顶向下思考,自底向上实现的,为了避免计算子问题时重复,可以将子问题的结果打表记录下来。

3贪心法:使用贪心法解决问题,要从数学上证明这个贪心策略一定能取到最优解,这样每一步都做贪心选择,实现起来要容易很多。

整数划分问题

动态规划与贪婪 剪绳子 12477 32.27%

给你一根长度为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,意义见题面。(2 <= n <= 60)

变式:切割杆,现有长度为n的杆,价值数组是prices[],数组长度是n,已知长度i对应的价值是prices[i-1],比如长度1对应的价值数是prices[0]。将其切割,求碎片的最大价值。

1) 将n划分成若干正整数之和的划分数。
2) 将n划分成k个正整数之和的划分数。
3) 将n划分成最大数不超过k的划分数。
4) 将n划分成若干奇正整数之和的划分数。
5) 将n划分成若干不同整数之和的划分数。

 

链接:https://www.nowcoder.com/questionTerminal/57d85990ba5b440ab888fc72b0751bf8?orderByHotValue=1&questionTypes=000100&mutiTagIds=592&page=1&onlyReference=false
来源:牛客网

 /**
     * @param target
     * @return
     *
     * 分类:最值型、划分型
     *
     * 考虑最后一步:
     * 必然有一个点,把target分成两段,两段分别构成最小子问题。
     * 两段的最大值的乘积,也是target所求的最大值。
     * 设划分点为i,f[i]表示长度为i的绳子的乘积最大值。
     *
     * 转移方程:
     * f[i] = MAX{f[j]*f[i-j]}|0<j<i
     *
     * 那么我们求的就是f[target]
     *
     * 初始值:
     * f[0]=1
     * f[1]=1
     *
     * 边界情况:
     * 无
     *
     * 计算顺序:
     * i从1到target
     * j从1到i
     */
    public int cutRope(int target) {
        int[] f = new int[target+1];
        //初始化
        f[0] = 0;
        f[1] = 1;
        for (int i = 1; i <= target; i++) {
            /**
             * 处理不分割的情况,因为绳子不能不被分割
             */
            if(i==target) {
                f[i] = 1;
            }
            else {
                f[i] = i;
            }
            for (int j = 1; j < i; j++) {
                f[i] = Math.max(f[i],f[j]*f[i-j]);
            }
        }
        return f[target];
    }

上面解法有暴力穷举的思想,递推问题都可以这么做

从i=1开始记录出每个长度i的绳子,最大乘积fi记录在数组f

对于每个fi需要转换为前几个状态的表达,即状态方程,才能求解

划分问题,引入一个变量j,代表从0~i的一种划分

至于本题,是取乘积最大对划分。

至于切割杆,是取划分后两部分价值最大。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章