每日一练(day03--动态规划dp)

Posted 'or 1 or 不正经の泡泡

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了每日一练(day03--动态规划dp)相关的知识,希望对你有一定的参考价值。

前言

最近两天被拉过去送新娘了,啥也没干。所以先来几道简单题找找自信(狗头)

题目

求算术平方

给你一个非负整数 x ,计算并返回 x 的 算术平方根 。

由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。

注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5) 或者 x ** 0.5 。

示例 1:

输入:x = 4 输出:2 示例 2:

输入:x = 8 输出:2 解释:8 的算术平方根是 2.82842…, 由于返回类型是整数,小数部分将被舍去

咋一看这个题目我就被吓到了,喵的不让用怎么算,想了半天我也不会别的方法呀,后来查了一下发现,喵的有种简化计算公式。
这个解法最简单。

e2lnx = x2

所以方法一就是直接套公式

class Solution 
    public int mySqrt(int x) 
        if (x == 0) 
            return 0;
        
        int ans = (int) Math.exp(0.5 * Math.log(x));
        return (long) (ans + 1) * (ans + 1) <= x ? ans + 1 : ans;
    


方法二就是二分法。就是猜测这个数字的范围。这个也很好理解上代码

class Solution 
    public int mySqrt(int x) 
        int left = 0, right = x, ans = -1;
        while (left <= right) 
            int mid = left + (right - left) / 2;
            if ((long) mid * mid <= x) 
                ans = mid;
                left = mid + 1;
             else 
                right = mid - 1;
            
        
        return ans;
    


爬楼梯

这个题目是一个经典的那个动态规划的题目,同时其实也是一个斐波那契数字的一个应用吧当初学python的时候我就记得那个书上老是喜欢那那个斐波那契数列和八皇后问题来玩,现在想想为什么当初没有从那个时候好好刷算法。

题目

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

注意:给定 n 是一个正整数。

示例 1:

输入: 2 输出: 2 解释: 有两种方法可以爬到楼顶。
1 阶 + 1 阶
2 阶 示例 2:

输入: 3 输出: 3 解释: 有三种方法可以爬到楼顶。
1 阶 + 1 阶 + 1 阶
1 阶 + 2 阶
2 阶 + 1 阶

思路其实很简单,你自己想想是吧,假设我要到第五个楼梯,那么我是不是可以直接从 第四个和第三个楼梯过来,那么到达第三个,第四个楼梯有几种方式,两个加起来就是第五个的过法,同时第三第四个又是从那里过来的,那么我们就可以得出结论,从 0 开始 0种走法, 到达第一个 有一种方式,第二个可以从第一个过来,也可以从第0个过来也就是 0 + 1 ,1种,以此类推

0 1 1 2 3 5 … 这不就是个数列么,这个数列几种写法这个题目几个解法。

我这里来个最简单的。

class Solution 
    public int climbStairs(int n) 
        int p = 0, q = 0, r = 1;
        for (int i = 1; i <= n; ++i) 
            p = q; 
            q = r; 
            r = p + q;
        
        return r;
    


那么这里说一下的就是这个动态规划的题目有个典型的特征,那就是,我们可以得到一个状态方程,也就是说,那个当前这一步操作,一定是由上一步,或者上几部得到的,会受到前面的影响,也就是可以得到一个状态方程
F(n) = F(n-m)+F(n-k),m,k是步长,同时我们可以得到一开始的初始状态,也就是初始迭代状态

这种类型的题目和那个高中的那种什么等比数列的那种大题的思维方式很像。

既然说到了这个我们再来几道和动态规划有关的题目吧。

杨辉三角


先说一下特点,仔细看最外层都是 1 ,第一第二层都是 1 也就是初始状态
中间的数字收到上面两个的影响,可以构建方程,所以没跑的动态规划,并且我们知道了状态方程和初始状态,那么接下来想要求取第几层的那个还不简单吗。

输入: numRows = 5 输出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]

这里我们用到二维数组去存,然后就行了。java版本的有点难看,这里给出 java 和 python 版本

class Solution 
    public List<List<Integer>> generate(int numRows) 
        List<List<Integer>> YanghuiSanJiao = new ArrayList<List<Integer>>();
        for (int i = 0; i < numRows; i++) 
            List<Integer> row = new ArrayList<Integer>();
            for (int j = 0; j <= i; ++j) 
                if (j == 0 || j == i) 
                    row.add(1);
                 else 
                    row.add(YanghuiSanJiao.get(i - 1).get(j - 1) + YanghuiSanJiao.get(i - 1).get(j));
                
            
            YanghuiSanJiao.add(row);
        
        return YanghuiSanJiao;
    


python

class Solution:
    def generate(self, numRows: int) -> List[List[int]]:
        YanghuiSanJiao = list()
        for i in range(numRows):
            row = list()
            for j in range(0, i + 1):
                if j == 0 or j == i:
                    row.append(1)
                else:
                    row.append(YanghuiSanJiao[i - 1][j] + YanghuiSanJiao[i - 1][j - 1])
            YanghuiSanJiao.append(row)
        return YanghuiSanJiao

杨辉三角2

这个就是小变形嘛

给定一个非负索引 rowIndex,返回「杨辉三角」的第 rowIndex 行。

在「杨辉三角」中,每个数是它左上方和右上方的数的和。

示例 1:

输入: rowIndex = 3 输出: [1,3,3,1]

class Solution 
    public List<Integer> getRow(int rowIndex) 
        List<List<Integer>> YanghuiSanJiao = new ArrayList<List<Integer>>();
        for (int i = 0; i <= rowIndex; ++i) 
            List<Integer> row = new ArrayList<Integer>();
            for (int j = 0; j <= i; ++j) 
                if (j == 0 || j == i) 
                    row.add(1);
                 else 
                    row.add(YanghuiSanJiao.get(i - 1).get(j - 1) + YanghuiSanJiao.get(i - 1).get(j));
                
            
            YanghuiSanJiao.add(row);
        
        return YanghuiSanJiao.get(rowIndex);
    


不同路径

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

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

问总共有多少条不同的路径?
输入:m = 3, n = 7
输出:28
示例 2:

输入:m = 3, n = 2 输出:3

这个也是一样的。

直接给代码了。

class Solution 
    public int uniquePaths(int m, int n) 
        int[][] f = new int[m][n];
        for (int i = 0; i < m; ++i) 
            f[i][0] = 1;
        
        for (int j = 0; j < n; ++j) 
            f[0][j] = 1;
        
        for (int i = 1; i < m; ++i) 
            for (int j = 1; j < n; ++j) 
                f[i][j] = f[i - 1][j] + f[i][j - 1];
            
        
        return f[m - 1][n - 1];
    


玩到这里比较简单的动态规划基本就这样了。

以上是关于每日一练(day03--动态规划dp)的主要内容,如果未能解决你的问题,请参考以下文章

每日一练(day09补08,03,04)

CSDN|每日一练小艺改编字符串

CSDN|每日一练小艺改编字符串

C语言每日一练 —— 第22天:动态规划

每日一练(day10)

每日一练(day01)