【力扣刷题 | 第十五天】

这篇具有很好参考价值的文章主要介绍了【力扣刷题 | 第十五天】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

【力扣刷题 | 第十五天】,【力扣刷题】,leetcode,算法,数学建模

目录

前言:

 ​​​​​​​63. 不同路径 II - 力扣(LeetCode)

343. 整数拆分 - 力扣(LeetCode)

总结:


前言:

        本篇我们主要刷动态规划的题,解题还是严格按照我们在【夜深人静写算法】栏目下的解题步骤,大家如果没学过动态规划的可以先看看我写的动态规划文章介绍。

【夜深人静学数据结构与算法 | 第十篇】动态规划_我是一盘牛肉的博客-CSDN博客

 文章来源地址https://www.toymoban.com/news/detail-614206.html

 ​​​​​​​63. 不同路径 II - 力扣(LeetCode)

一个机器人位于一个 m * n 网格的左上角 (起始点在下图中标记为 “Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish”)。

现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?

网格中的障碍物和空位置分别用 1 和 0 来表示。

【力扣刷题 | 第十五天】,【力扣刷题】,leetcode,算法,数学建模其实这题跟我们在动态规划中讲解的例题答题思路基本一致,就是需要再加一个判断条件:
如果这块是障碍点,那么我们就将这个点的路径数设置为0,并且放弃这条路。

class Solution {
public:
    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
        int m = obstacleGrid.size();
        int n = obstacleGrid[0].size();
	if (obstacleGrid[m - 1][n - 1] == 1 || obstacleGrid[0][0] == 1) //如果在起点或终点出现了障碍,直接返回0
       { 
            return 0;
       }    
        vector<vector<int>> dp(m, vector<int>(n, 0));
        for (int i = 0; i < m && obstacleGrid[i][0] == 0; i++)//obstacleGrid[i][0] == 0也就是没有障碍物
        {
            dp[i][0] = 1;
        } 
        for (int j = 0; j < n && obstacleGrid[0][j] == 0; j++)// obstacleGrid[0][j] == 0也就是没有障碍物
        {
             dp[0][j] = 1;
        };

        for (int i = 1; i < m; i++) {
            for (int j = 1; j < n; j++) {
                if (obstacleGrid[i][j] == 1)
                {
                    continue;
                } 
                dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
            }
        }
        return dp[m - 1][n - 1];

    }
};

343. 整数拆分 - 力扣(LeetCode)

给定一个正整数 n ,将其拆分为 k 个 正整数 的和( k >= 2 ),并使这些整数的乘积最大化。

返回 你可以获得的最大乘积 。

【力扣刷题 | 第十五天】,【力扣刷题】,leetcode,算法,数学建模

 其实这道题我们要明白:要想使得拆出来的整数乘积大,我们就要尽量的保证拆出来的整数接近。也就是尽可能拆出来相同的数。

关于为什么是这样的,我们需要用数学公式解决:

这个问题可以通过数学方法进行解释,思路如下:

假设将整数 n 拆分成 k 个正整数相加,这 k 个正整数分别为 a1, a2, ..., ak,则它们的乘积为:

P = a1 * a2 * ... * ak

我们可以对这个乘积进行求导,得到:

dP/da1 = a2 * a3 * ... * ak
dP/da2 = a1 * a3 * ... * ak
...
dP/da(k-1) = a1 * a2 * ... * a(k-1)
dP/da(k) = a1 * a2 * ... * a(k-1)

由于这k个正整数相加得到的和为n,因此有:

a1 + a2 + ... + ak = n

可以使用拉格朗日乘数法求解上面的一组方程,得到:

a1 = n / k
a2 = n / k
...
ak-1 = n / k
ak = n - (k-1) * n / k

可以看到,当 k 越大时,每个数都越趋近于相等,因此其乘积也会越来越大,直到取到最大值。

因此,我们可以通过枚举每个 k,来找到乘积最大的 k 和对应的乘积。

看不懂也没有关系,知道这个结论就可以了,但是如果更好的理解这个数学验证的话,我们就可以在验证的时候做更好的优化。

class Solution {
public:
    int integerBreak(int n) {
        vector<int> dp(n + 1);
        dp[2] = 1;
        for (int i = 3; i <= n ; i++) {
            for (int j = 1; j <= i / 2; j++) {
                dp[i] = max(dp[i], max((i - j) * j, dp[i - j] * j));
            }
        }
        return dp[n];
    }
};

但其实本道题还可以用贪心算法的思路来做,但是贪心算法的代码虽然简洁,但是数学公式证明起来比较麻烦。

本题是可以用贪心算法进行求解的。

1. 当n>=5时,将n拆分成3和n-3的和,比将其拆分成2和n-2的和要优秀,即:

            n-3 > n-2 && 3*(n-3) > 2*(n-2)
   
   这个性质可以通过一系列代数计算证明。

2. 当n>=5时,将n拆分成3的个数不会小于将其拆分成2的个数,即:

            n mod 3 <= 1
   
   这个性质也可以通过一系列代数计算证明。

基于以上结论,可以采用贪心算法,将整数n尽可能地拆分成3的和,直到最后得到的整数小于5。如果最后得到的整数等于1,则将其与最后一个3合并为4。

这种贪心策略的正确性可以通过数学归纳法证明。这里只给出其中一个例子:

        当n=6时,根据以上贪心策略,将其拆分成3和3的和,乘积为9。然而,将其拆分成2和2和2的和,乘积为8,不是最优解。但是,当n=5时,按照贪心策略,将其拆分成3和2的和,乘积为6;而将其拆分成2和3的和,乘积为5,不是最优解。又因为任何大于5的整数都可以通过一系列的拆分得到6和2或3的和,因此对于所有大于5的整数,采用贪心策略是最优的。

因此,可以使用贪心算法来解决这个问题。

class Solution {
public:
    int integerBreak(int n) {
        if (n == 2) return 1;
        if (n == 3) return 2;
        if (n == 4) return 4;
        int result = 1;
        while (n > 4) {
            result *= 3;
            n -= 3;
        }
        result *= n;
        return result;
    }
};

总结:

        在做动态规划的时候,我们如果是初学的话,要牢牢按照动态规划五步走,这样才可以完整的解题,而不是稀里糊涂的看题解。

如果我的内容对你有帮助,请点赞,评论,收藏创作不易,大家的支持就是我坚持下去的动力!

【力扣刷题 | 第十五天】,【力扣刷题】,leetcode,算法,数学建模

 

到了这里,关于【力扣刷题 | 第十五天】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • leetcode 力扣刷题 旋转矩阵(循环过程边界控制)

    下面的题目的主要考察点都是,二维数组从左上角开始顺时针(或者逆时针)按圈遍历数组的过程。顺时针按圈遍历的过程如下: 对于每一圈,分为四条边 ,循环遍历就好。这时,对于 四个角 的元素的处理,可以将四条边的遍历分为以下两种情况: 第一种:每条边都从对

    2024年02月12日
    浏览(48)
  • 【leetcode 力扣刷题】移除链表元素 多种解法

    题目链接:203.移除链表元素 题目内容: 理解题意:就是单纯的删除链表中所有值等于给定的val的节点。上一篇博客中介绍了链表的基础操作,在删除链表中节点时,需要注意的是头节点: 如果没有虚拟头节点,那么对头节点的删除需要做不同的处理,head = head-next; 如果有

    2024年02月12日
    浏览(48)
  • 【leetcode 力扣刷题】链表基础知识 基础操作

    在数据结构的学习过程中,我们知道线性表【一种数据组织、在内存中存储的形式】是线性结构的,其中线性表包括顺序表和链表。数组就是顺序表,其各个元素在内存中是连续存储的。 链表则是由 数据域 和 指针域 组成的 结构体 构成的,数据域是一个节点的数据,指针域

    2024年02月12日
    浏览(39)
  • 【leetcode 力扣刷题】回文串相关题目(KMP、动态规划)

    题目链接:5. 最长回文子串 题目内容: 题目就是要我们找s中的回文子串,还要是最长的。其实想想,暴力求解也行……就是遍历所有的子串,同时判断是不是回文串,是的话再和记录的最大长度maxlen比较,如果更长就更新。时间复杂度直接变成O(n^3)。 优化的点在于,假设子

    2024年02月09日
    浏览(48)
  • 【leetcode 力扣刷题】字符串翻转合集(全部反转///部分反转)

    题目链接:344. 反转字符串 题目内容: 题目中重点强调了必须 原地修改 输入数组,即不能新建一个数组来完成字符串的反转。我们注意到: 原来下标为0的,反转后是size - 1【原来下标是size - 1的,反转后是0】; 原来下标是1的,反转后是size - 2【原来下标是size -2的,反转后

    2024年02月11日
    浏览(46)
  • 【leetcode 力扣刷题】字符串匹配之经典的KMP!!!

    以下是能用KMP求解的算法题,KMP是用于字符串匹配的经典算法【至今没学懂………啊啊啊】 题目链接:28. 找出字符串中第一个匹配项的下标 题目内容: 题意还是很好理解的,要在字符串haystack中查找一个完整的needle,即字符串匹配。 暴力求解就是用 两层循环 :haystack从第

    2024年02月09日
    浏览(42)
  • 力扣刷题-动态规划算法3:完全背包问题

    问题描述: 1)有N件物品和一个最多能背重量为W的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。 2) 每件物品都有无限个(也就是可以放入背包多次) (比0-1背包多出的条件) 3) 求解将哪些物品装入背包里物品价值总和最大。 求解步骤: 1)首先遍历物品,然

    2023年04月13日
    浏览(58)
  • 【leetcode 力扣刷题】数学题之除法:哈希表解决商的循环节➕快速乘求解商

    题目链接:166. 分数到小数 题目内容: 题目是要我们把一个分数变成一个小数,并以字符串的形式返回。按道理,直接将分子numerator除以分母denominator就得到了小数,转换成string返回就好。题目要求里指出了特殊情况—— 小数部分如果有循环,就把循环节括在括号里 。 那么

    2024年02月10日
    浏览(40)
  • 力扣刷题之旅:高级篇(六)—— 网络流算法:Edmonds-Karp 算法与实际应用

               力扣(LeetCode) 是一个在线编程平台,主要用于帮助程序员提升算法和数据结构方面的能力。以下是一些力扣上的入门题目,以及它们的解题代码。              目录 引言  一、Edmonds-Karp 算法简介 二、算法实现 下面是使用 Python 实现的 Edmonds-Karp 算法:

    2024年02月22日
    浏览(41)
  • 数据结构:力扣刷题

      给你一个  升序排列  的数组  nums  ,请你  原地  删除重复出现的元素,使每个元素  只出现一次  ,返回删除后数组的新长度。元素的  相对顺序  应该保持  一致  。然后返回  nums  中唯一元素的个数。 考虑  nums  的唯一元素的数量为  k  ,你需要做以下事情确

    2024年02月13日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包