DW&LeetCode_day8(62、70、78)

DW&LeetCode_day8(62、70、78)


写在前面:

  • 第8天开始了,今天开始加油吧!

开源内容

开源内容


目录

DW&LeetCode_day7(62、70、78)

写在前面:

开源内容

学习大纲 

 62. 不同路径

题解:

70. 爬楼梯

 题解:

78. 子集

题解:


学习大纲 

 62. 不同路径

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

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

问总共有多少条不同的路径?

示例 1:


输入:m = 3, n = 7
输出:28


示例 2:

输入:m = 3, n = 2
输出:3
解释:
从左上角开始,总共有 3 条路径可以到达右下角。
1. 向右 -> 向右 -> 向下
2. 向右 -> 向下 -> 向右
3. 向下 -> 向右 -> 向右


示例 3:

输入:m = 7, n = 3
输出:28


示例 4:

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

提示:

1 <= m, n <= 100
题目数据保证答案小于等于 2 * 109

来源:力扣(LeetCode)
链接:题目链接

题解:

Python中的Math库包含许多数学运算,可以使用该模块轻松执行。

math.comb()Python中的method方法用于获取从n个项目中选择k个项目(不重复且无顺序)的方法数量。

它本质上评估为n! /(k!*(n-k)!)它也被称为二项式系数,因为它等效于表达式(1 + x)的多项式展开中的k-th项的系数n。
 

用法: math.comb(n, k)

参数:

  • n:非负整数
  • k:非负整数

 

返回:一个整数值,表示从n个项目中选择k个项目(无重复且无顺序)的方式数量。

class Solution:
    def uniquePaths(self, m: int, n: int) -> int:
        return math.comb(m-1+n-1, m-1)

 组合公式C(n-1, m+n-2)=C(m-1, m+n-2)  , 总共走的步长为m+n-2,纵向 必然要走 m-1 步, 横向必然走n-1 步,从里面寻找 (n-1) 或 (m-1) 的组合

class Solution:
    def uniquePaths(self, m: int, n: int) -> int:
        M, N = 1, 1
        for i in range(2,min(m,n)):N *= i # min(m,n)-1 +1  # m,n --> 3, 7  C(2, 8)  --> 8*7 // 2*1
        for i in range(m+n-2, m+n-2 - (min(m,n)-1), -1):M *= i
        return M//N

   时间复杂度 O(max(m,n)), 空间复杂度 O(1) 

70. 爬楼梯

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

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

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

示例 1:

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


示例 2:

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

 题解:

 

状态转移方程f(n) = f(n-1) + f(n-2)
下一步要到达第n级阶梯有两种方式

  •  一是从第n-1阶跨1阶到达,
  • ’二是从第n-2阶跨2阶到达,而到达n-1阶和n-2阶的组合数分别为dp(n-1)和dp(n-2),加起来则为到达n阶的结果。

时间复杂度O(n)
dp[i]保存状态,即i个台阶需要多少种方法

 

emmm,递归超时了!lj

class Solution:
    def climbStairs(self, n: int) -> int:
        a = [0, 1]
        for i in range(n):a[i%2] = a[i%2] + a[(i+1)%2]
        b = a[(n+1)%2]
        return b

image.png

 斐波那契数列

1个台阶1种
2个台阶有2种:[1,1] [2]
3个台阶有3种:[1,1,1] [1,2] [2,1]
4个台阶有5种:[1,1,1,1] [1,1,2] [1,2,1] [2,1,1] [2,2]
// 一个C++做法
class Solution {
public:
    int climbStairs(int n) {
        int first = 0, res = 1;
        for (int i = 1; i <= n ; i ++) 
            res += first, first = res - first;
        return res;
    }
};

 

78. 子集

给你一个整数数组 nums ,返回该数组所有可能的子集(幂集)。解集不能包含重复的子集。

 
示例 1:

输入:nums = [1,2,3]
输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]


示例 2:

输入:nums = [0]
输出:[[],[0]]
 

提示:

1 <= nums.length <= 10
-10 <= nums[i] <= 10
链接:题目链接

题解:

# 划分两部分内容,最后第一份含有一个给定元素,那么另一份就不含有这个元素
class Solution:
    def subsets(self, n : List[int]) -> List[List[int]]:
        if not n:return [[]]
        r=self.subsets(n[:-1])
        return r+[a+[n[-1]] for a in r]

借用一下图 @liweiwei1419

image.png回溯三个元素:


a结束条件 b。递归作用找出所有子集 c等价条件:当前选择的+之后选择的==取消这一步选择的,重新这一步选择并选另一个元素

  •     1.结束开头的if return 当到达一个特定结束条件时候,就认为这个一步步构建的解是符合要求的解了,可以返回并开始回溯操作了,注意也可以是递归到底的结束
  •     2.把解存下来或者打印出来的操作:递归以上的部分
  •     3.递归的选择,既先递归
  •     4.本次推进结束后,如何回溯到上一步:如pop

    注意:

    1.pop后要不要接一个递归:一般pop前有两此递归则不用,否则要接,不然pop结束后直接返回到上一步递归结束后执行下一个递归语句了
    2.可能连续两次递归的结束才代表一轮结束,开始回溯,这个时候pop后就不用加递归了
 

  • 长度超过size后本轮结束
  • 下两语句存值
  • 递归:作用是每次递归存入一个nums的子集向量(所以i来推进)
  • 结束时,pop一个,回到上一步i值相同但没有选2的操作推进
class Solution {
    void generate(int i,vector<int>& nums,vector<int>& item, vector<vector<int>>& result){
        if(i>=nums.size()) return;//i是从0开始,所以范围0~size-1,即推进结束时候第一次递归结束

        item.push_back(nums[i]);//把当前第i元素push
        result.push_back(item);//把此时的这个向量num,push

        generate(i+1, nums,item,result );//第一次递归,num往后推进,不断push
        item.pop_back();//推进结束,pop最后的那个出来
        generate(i+1,nums,item,result);//回退到当上一个元素(3)不选时候,进行的第二次递归选择
       //详细内部细节: //第二次的i是当前上一步语句的i2,i+1=3,也就是说i=2时候,进行gene(i+1=3)递归,return了,pop后,gene(3),rfeturn,后此刻总的genere(i=2)这个递归结束返回,而这个gene(2),对应的是gene(1)总递归里面的,gene(1+1)这第一次递归,此时返回到这里了然后pop,进行第二次递归。
        //i=1,对应于选2和不选2 的情况,回溯就是第一次回退一步选不选3,然后不选3 时候情况,第二次回退到选不选2的那一步,然后执行不选2的那一步计算,会是什么情况,而不选2时候,i自然和选2的时候一样加1了,变成了 i=2,此时item只有1(因为2pop走了)执行gene(2)时候,push(nums(2))也就是3push进此时的item里 item{1,3},情况出现
          //最后加不加return都无所谓,因为这个地方就结束了,必定是要返回的
    }
public:
    vector<vector<int>> subsets(vector<int>& nums) {
        vector<int> item={};//item用来承装nums各个情况,初始化为空,然后先放进item中,因为题目要求result里面得有个空向量
        vector<vector<int>> result;
        result.push_back(item);//放进这个空向量
        //开始回溯法放入nums
        generate(0,nums,item,result);
        return result;
    }
}

 

 

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值