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];
}
};