LeetCode-343. 整数拆分

题目描述

给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化。 返回你可以获得的最大乘积。

例如,给定 n = 2,返回1(2 = 1 + 1);给定 n = 10,返回36(10 = 3 + 3 + 4)。

注意:你可以假设 n 不小于2且不大于58。

感谢:
特别感谢 @jianchao.li.fighter 添加此问题并创建所有测试用例。

思路

递归求解

首先将原问题拆分成可递归的子问题,如果mem[n]表示正整数n的最大成绩,则递归方程就是mem[n] = max(imem[n-i], i(n-i)),递归终止条件为mem[1] = 1,根据递归方程可以得到递归解法。

class Solution {
public:
    int integerBreak(int n) 
    {
        return maxBreakInteger(n);
    }
private:
    int maxBreakInteger(int n)
    {
        if (n == 1)
            return 1;

        int res = -1;
        for(int i = 1; i < n;++i)
        {
            res = max(max(res ,i*(n-i)), i * maxBreakInteger(n-i));
        }
        return res;
    }
};

进一步利用路径记忆进行优化

class Solution {
public:
    int integerBreak(int n) 
    {
        m_mem = vector<int>(n+1, -1);
        return breakInteger(n);
    }
private:
    int breakInteger(int n)
    {
        if (n == 1)
            return 1;
        if (m_mem[n] != -1)
            return m_mem[n];

        int res = -1;
        for(int i = 1; i < n;++i)
        {
            res = max(max(res ,i*(n-i)), i * breakInteger(n-i));
        }
        m_mem[n] = res;
        return res;
    }
    vector<int> m_mem;
};

动态规划

根据上面带路径记忆的递归算法,进一步利用动态规划进行优化。

class Solution {
public:
    int integerBreak(int n) 
    {
        vector<int> mem(n+1, -1);
        mem[1] = 1;
        for(int i = 2;i <= n; ++i)
        {
            for(int j = 1; j <= i-1; j++)
            {
                mem[i] = max(max(mem[i] ,j*(i-j)), j*mem[i-j]);
            }
        }
        return mem[n];
    }
};
posted @ 2018-07-02 09:00  Blue影  阅读(308)  评论(0编辑  收藏  举报