算法期中练习——1005. 最小和

算法期中练习——1005. 最小和

Description:

从数列A[0], A[1], A[2], …, A[N-1]中选若干个数,要求对于每个i(0 <= i < N-1),A[i]和A[i+1]至少选一个数,求能选出的最小和.
1 <= N <= 100000, 1 <= A[i] <= 1000

Example:

例1:A = {2, 5, 2},答案为4.
例2:A = {2, 5, 4},答案为5.

请为下面的Solution类实现解决上述问题的函数minSum,函数参数A是给出的数列,返回值为所求的最小和.

class Solution {
public:
    int minSum(vector<int>& A) {

    }
};

分析:

动态规划的问题:这道题在考试的时候做不出来,动态规划有那么一个痛点,就是明明知道要用动态规划来求解,然而子问题很难分析出来,更别说求解的递归公式了。
考完试后,看了大神的代码,理解了一下,就是最后一个数选不选的问题,如果不选,说明前一个数一定选,而选的话无法确定前一个数是否选,因此需不断比较之前的数是否选,返回最后一个数选和最后一个数不选的比较结果(最小)。

可能说起来比较难懂,我们看看下面两个解法的手工求解过程:

Solution #1
例1:
sum[0]=2, sum[1]=5, sum[2]=min(4, 7)=4
return min(4, 5)=4

例2:
sum[0]=2, sum[1]=5, sum[2]=min(6, 9)=6
return min(6, 5)=5

代码如下:

class Solution {
public:
    int minSum(vector<int>& A) {
        int size = A.size();
        vector<int> sum(size, 0);//sum[size-1]表示最后一个被选中时的最小和
        sum[0] = A[0];
        if (size > 1) sum[1] = A[1];

        for (int i = 2; i < size; i++) {
            sum[i] = min(sum[i - 2] + A[i], sum[i - 1] + A[i]);
        }
        if (size == 1) return sum[0];
        else return min(sum[size - 1], sum[size - 2]);
    }
};

Solution #2:
f[0][i]存储最后一个数不选的结果;
f[1][i]存储最后一个数选的结果。

例1:
f[0][0]=0, f[1][0]=2
f[0][1]=2, f[0][2]=5
f[0][2]=5, f[1][2]=4
return min(f[0][2], f[1][2])=min(5, 4)=4

例2:
f[0][0]=0, f[1][0]=2
f[0][1]=2, f[1][2]=5
f[0][2]=5, f[1][2]=6
return min(f[0][2], f[1][2])=min(5, 6)=5

代码如下:

class Solution {
private:
    vector<int> f[2];
public:
    int minSum(vector<int>& A) {
        int n, i;
        n = A.size();
        if (n == 0) return 0;
        f[0].resize(n);
        f[1].resize(n);
        f[0][0] = 0;
        f[1][0] = A[0];
        for (i = 1; i < n; i++) {
            f[0][i] = f[1][i - 1];
            f[1][i] = A[i] + min(f[0][i - 1], f[1][i - 1]);
        }
        return min(f[0][n - 1], f[1][n - 1]);
    }
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值