03.09

 剑指 Offer II 100. 三角形中最小路径之和

class Solution {
public:
    int minimumTotal(vector<vector<int>>& triangle) {
        //获取长度
        int n = triangle.size();
        //创建数组
        vector<vector<int>> f(n, vector<int>(n));
        //初始化
        f[0][0] = triangle[0][0];
        //进行循环
        for (int i = 1; i < n; ++i) {
            f[i][0] = f[i - 1][0] + triangle[i][0];
            for (int j = 1; j < i; ++j) {
                f[i][j] = min(f[i - 1][j - 1], f[i - 1][j]) + triangle[i][j];
            }
            f[i][i] = f[i - 1][i - 1] + triangle[i][i];
        }
        //返回最小值
        return *min_element(f[n - 1].begin(), f[n - 1].end());
    }
};

 剑指 Offer II 101. 分割等和子集

class Solution {
public:
    bool canPartition(vector<int>& nums) {
        int n = nums.size();
        //无法分割
        if (n < 2) {
            return false;
        }
        //元素和
        int sum = accumulate(nums.begin(), nums.end(), 0);
        //最大元素
        int maxNum = *max_element(nums.begin(), nums.end());
        //sum是奇数无法分割
        if (sum & 1) {
            return false;
        }
        //目标值为和的一半
        int target = sum / 2;
        //如果最大元素大于目标值 也无法分割
        if (maxNum > target) {
            return false;
        }
        //创建dp[n][target + 1]
        vector<vector<int>> dp(n, vector<int>(target + 1, 0));
        //target为0 全都满足
        for (int i = 0; i < n; i++) {
            dp[i][0] = true;
        }
        //第一个数字选择也满足
        dp[0][nums[0]] = true;
        for (int i = 1; i < n; i++) {
            int num = nums[i];
            for (int j = 1; j <= target; j++) {
                //元素值小于目标值
                //分为两种情况 
                //选择num dp[i - 1][j - num]
                //不选择num dp[i - 1][j]
                if (j >= num) {
                    dp[i][j] = dp[i - 1][j] | dp[i - 1][j - num];
                //元素值大于目标值
                //不能选择
                } else {
                    dp[i][j] = dp[i - 1][j];
                }
            }
        }
        //返回是否存在0-n-1 存在和等于目标值的
        return dp[n - 1][target];
    }
};

 剑指 Offer II 102. 加减的目标值

class Solution {
public:
//neg为前面加上- 的元素的和 
//(sum−neg)为前面加上+ 的元素的和
//(sum−neg)−neg=sum−2⋅neg=target 
//neg=(sum−target​)/2 
    int findTargetSumWays(vector<int>& nums, int target) {
        int sum = 0;
        for (int& num : nums) {
            sum += num;
        }
        int diff = sum - target;
        //sum−target​非负偶数
        if (diff < 0 || diff % 2 != 0) {
            return 0;
        }
        int n = nums.size(), neg = diff / 2;
        //创建dp[n + 1][target + 1]
        vector<vector<int>> dp(n + 1, vector<int>(neg + 1));
        //target为0 全都满足
        dp[0][0] = 1;
        for (int i = 1; i <= n; i++) {
            int num = nums[i - 1];
            for (int j = 0; j <= neg; j++) {
                //元素值小于目标值
                //分为两种情况 
                //选择num dp[i - 1][j - num]
                //不选择num dp[i - 1][j]
                if (j >= num) {
                    dp[i][j] = dp[i - 1][j]+dp[i - 1][j - num];
                //元素值大于目标值
                //不能选择
                } else {
                    dp[i][j] = dp[i - 1][j];
                }
            }
        }
        return dp[n][neg];
    }
};

 

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值