LeetCode刷题笔记(Integer Break)

据说这次台风来势凶猛,怪不得北京的天气如此反常,连续数周阴雨绵绵,但愿台风赶快离我国而去,愿更少的众生受到更少的伤害。言归正传,刚刷了一道题感觉难度还行,下面就和大家分享一下经验吧!

题目如下:

题意分析:

给定一个正整数n,请将它至少分成两个正整数且需要满足这些正整数之和为n,同时从n的所有划分方法中找出划分后各正整数的最大乘积,并返回。

方法一(记忆化搜索法)

先通过“自顶向下”思考即递归思想,形成一颗树,如下图所示。很显然从图中可以看出,存在不少的重叠子问题,所以可以在递归中加入记忆化以减少时间复杂度。

解题代码如下:

class Solution{
private:
    vector<int> memo;
    int max3( int a, int b, int c ){
        return max( a, max(b, c) );
    }
    int findintegerBreak( int n ){
        if ( n == 1 ) return 1;
        if ( memo[n] != -1)
            return memo[n];

        int res = -1;
        for ( int i = 1; i < n; i++ ) {
            res = max3( res, i*(n - i), i*findintegerBreak(n - i) );
        }
        memo[n] = res;
        return res;
    }

public:
    int integerBreak( int n ){
        if ( n == 0 ) return 0;
        if ( n == 1 ) return 1;
        memo = vector<int>( n+1, -1 );
        return findintegerBreak( n );
    }
};

提交后的结果如下: 

 

方法二(动态规划法)

一般递归问题满足以下两个条件,那么既可以用记忆化搜索的方法解决也可以用动态规划的方法解决,不过一般先用记忆化搜索的方法(自顶向下),然后再用动态规划的方法(自底而上):① 求解原问题时,有重叠子问题,② 求解原问题时,有最优子结构,即通过求解子问题的最优解可以获得原问题的最优解。 

有了方法一的基础,方法二就很容易想了,主要是维护一个数组memo,让其记录到达某个正整数时的最大乘积,以便后面的正整数在划分时直接调用,这样可以大大减小时间复杂度。

解题代码如下:

class Solution{
public:

    int max3( int a, int b, int c ){
        return max( a, max(b, c) );
    }
    int integerBreak( int n ){
        vector<int> memo( n+1, -1 );
        memo[1] = 1; 
        for (int i = 2; i <= n; i++) {
            for (int j = 1; j <= i-1; ++j) {
                 memo[i] = max3( memo[i], j*(i-j), j*memo[i-j] );   
            }
        }
        return memo[n];
    }
};

提交后的结果如下: 

 

 

 

日积月累,与君共进,增增小结,未完待续。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值