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)
既然无论如何时间都会过去,为什么不选择做些有意义的事情呢