LeetCode Easy: 70. Climbing Stairs

一、题目

You are climbing a stair case. It takes n steps to reach to the top.

Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?

Note: Given n will be a positive integer.

Example 1:

Input: 2
Output:  2
Explanation:  There are two ways to climb to the top.

1. 1 step + 1 step
2. 2 steps

Example 2:

Input: 3
Output:  3
Explanation:  There are three ways to climb to the top.
1. 1 step + 1 step + 1 step
2. 1 step + 2 steps
3. 2 steps + 1 step
爬楼梯,每次只能爬一步或者两步,看一共有多少爬法。

二、思路
首先肯定能用递归来计算,到达第 i 个位置时,都有两种选择,爬一步(此时可以表示成 i - 1 位置上然后上一步),或者爬两步(此时可以看成 i - 2 位置然后跨两步),所以此问题到达第 i 个位置可能
的结果可以表示成第 i - 1 位置上的结果 + i - 2 位置上的结果。跟斐波那契数列一样。所以代码可以这样写:
def climbStairs2(n):
    if n == 1:
        return 1
    elif n == 2:
        return 2
    else:
        print(climbStairs2(n-1)+climbStairs2(n-2))
        return climbStairs2(n-1)+climbStairs2(n-2)
但是递归一般是像我这样的菜鸡才用的,高手一般都不用递归,有点慢,会重复计算很多之前计算过的步骤。于是我花了点时间学习了动态规划,其实我感觉相比较递归,动态规划就是把递归过程中的子问题的解
集用一个数组保存下来,以备后用,整体上我感觉跟递归的差距就在这里了,同样也是把一个大问题分成好多小问题,然后解决每一个小问题的最优解,最后汇集。这是我的观点,由于接触时间比较短,有说错的
地方还请大神提点。
动态规划的代码如下,用三个变量保存结果:
def climbStairs(n):
    """
    :type n: int
    :rtype: int
    """
    n_1 = 1
    n_2 = 0
    for i in range(1,n+1):
        tmp = n_1+n_2
        n_2 = n_1
        n_1 = tmp
    print(tmp)
    return tmp

学习动态规划的一些例子和代码如下:

#coding:utf-8
import numpy as np
def climbStairs(n):
    """
    :type n: int
    :rtype: int
    """
    n_1 = 1
    n_2 = 0
    for i in range(1,n+1):
        tmp = n_1+n_2
        n_2 = n_1
        n_1 = tmp
    print(tmp)
    return tmp

"""
给定一个数组,每次取出来的必须不相邻,求出能取出来的数加起来最大
"""
#1递归做法
def rec_opt(arr,i):
    if i == 0:
        return arr[0]
    elif i ==1:
        return max(arr[0],arr[1])
    else:
        A = rec_opt(arr,i-2)+arr[i]
        B = rec_opt(arr,i-1)
        print(max(A,B))
        return max(A,B)

#2、非递归做法
def dp_opt(arr):
    opt = np.zeros(len(arr))
    opt[0] = arr[0]
    opt[1] = max(arr[0],arr[1])
    for i in range(2,len(arr)):
        A = opt[i-2]+arr[i]
        B = opt[i-1]
        opt[i] = max(A,B)
    print(opt[len(arr)-1])
    return opt[len(arr)-1]

"""
arr={3,34,4,12,5,2} S = 9,均为正整数
如果arr中存在数据加起来等于S,就返回true,否则flase
对于每个数都有两种可能,选或者不选
"""
#1、递归做法
def rec_subset(arr,i,s):
    if s == 0:
        return True
    elif i == 0:
        return arr[0] == s
    elif arr[i] > s:
        return rec_subset(arr,i-1,s)
    else:
        A = rec_subset(arr,i-1,s-arr[i])
        B = rec_subset(arr,i,s-arr[i])
        print(A or B)
        return A or B

#2、非递归其实就是用数组保存重叠的子问题
def dp_subset(arr,S):
    subset = np.zeros((len(arr),S+1),dtype=bool)
    subset[:,0] = True
    subset[0,:] = False
    subset[0,arr[0]] = True
    for i in range(1,len(arr)):
        for s in range(1,S+1):
            if arr[i] > s:
                subset[i,s] = subset[i-1,s]
            else:
                A = subset[i-1,S-arr[i]]
                B = subset[i-1,s]
                subset[i,s] = A or B
    r,c = subset.shape
    print(subset[r-1,c-1])
    return subset[r-1,c-1]

def climbStairs2(n):
    if n == 1:
        return 1
    elif n == 2:
        return 2
    else:
        #print(climbStairs2(n-1)+climbStairs2(n-2))
        return climbStairs2(n-1)+climbStairs2(n-2)



if __name__ == '__main__':
    #climbStairs2(4)
    climbStairs(4)
    arr = [1,2,4,1,7,8,3]
    arr1 = [4,1,1,9,1]
    arr2 = [3,34,4,12,5,2]
    #rec_opt(arr,6)   #出现很多重叠子问题,采用递归会很慢
    #dp_opt(arr)
    #rec_subset(arr2,len(arr2)-1,9)
    #dp_subset(arr2,12)


既然无论如何时间都会过去,为什么不选择做些有意义的事情呢
原文地址:https://www.cnblogs.com/xiaodongsuibi/p/8681816.html