LeetCode日记——【算法】动态规划专题——斐波那契数列
题1:爬楼梯
难度:Easy
题目描述:
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。
示例 :
输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。
1. 1 阶 + 1 阶 + 1 阶
2. 1 阶 + 2 阶
3. 2 阶 + 1 阶
代码:
class Solution { public int climbStairs(int n) { int p = 0, q = 0, r = 1; for (int i = 1; i <= n; ++i) { //p=f(n-2) p = q; //qf(n-1)=r q = r; //f(n)=f(n-1)+f(n-2) r = p + q; } return r; } }
分析:
我们用 f(x)f(x) 表示爬到第 xx 级台阶的方案数,考虑最后一步可能跨了一级台阶,也可能跨了两级台阶,所以我们可以列出如下式子:
f(x) = f(x - 1) + f(x - 2)
它意味着爬到第 x 级台阶的方案数是爬到第 x - 1 级台阶的方案数和爬到第 x - 2 级台阶的方案数的和。很好理解,因为每次只能爬 1 级或 2 级,所以 f(x)只能从 f(x - 1)和 f(x - 2) 转移过来,而这里要统计方案总数,我们就需要对这两项的贡献求和。
题2:打家劫舍
难度:Easy
题目描述:
你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。
示例 1:
输入:[1,2,3,1]
输出:4
解释:偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。
偷窃到的最高金额 = 1 + 3 = 4 。
代码:
class Solution { public int rob(int[] nums) { if (nums.length==0) return 0; int p = 0, q = 0, r = nums[0]; for (int i = 1; i < nums.length; i++) { p = q; q = r; r = Math.max(p+nums[i],q); } return r; } }
分析:
思路与第一道基本相同。不同的地方在于,转移方程为:maxMoney(n)=max(maxMoney(n-2)+nums[i],maxMoney(n-2))
题3:强盗在环形街区抢劫
难度:Easy
题目描述:
你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都围成一圈,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组,计算你在不触动警报装置的情况下,能够偷窃到的最高金额。
示例 1:
输入: [2,3,2]
输出: 3
解释: 你不能先偷窃 1 号房屋(金额 = 2),然后偷窃 3 号房屋(金额 = 2), 因为他们是相邻的。
代码:
class Solution { public int rob(int[] nums) { int len = nums.length; if(len==0) return 0; if(len==1) return nums[0]; //不偷最后一个 int p1 = 0, q1 = 0, sum1 = nums[0]; for (int i = 1; i < len-1; i++) { p1 = q1; q1 = sum1; sum1 = Math.max(p1+nums[i],q1); } //不偷第一个 int p2 = 0, q2 = 0, sum2 = nums[1]; for (int i = 2; i < len; i++) { p2 = q2; q2 = sum2; sum2 = Math.max(p2+nums[i],q2); } return Math.max(sum1,sum2); } }
分析:
这个程序是我看了思路之后自己写出来的!!太不容易了!
思路是在上一题的基础上,分成两部分计算:偷第一家,不偷最后一家。或偷最后一家,不偷第一家。然后选择这两种方案钱更多的那一种。