1.爬楼梯
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。
示例 1:
输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。
1. 1 阶 + 1 阶
2. 2 阶
这种题目是最单的动态规划,可以分解为子问题的求解,然后根据子问题来求解当前问题。
爬到当前楼层n的方法 = 爬到 n-1层的方法 + 爬到n-2层的方法
public int climbStairs(int n) {
if (n==1){
return 1;
}
if (n==2){
return 2;
}
int first = 1;
int second = 2;
for (int i = 2; i < n; i++) {
int temp = first + second;
first = second;
second = temp;
}
return second;
}
2.买股票的最佳时机
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。
如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。
注意你不能在买入股票前卖出股票。
示例 1:
输入: [7,1,5,3,6,4]
输出: 5
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格。
思路:设置一个变量保存最低的股价,一个变量保存最大的利润,如果当前的股价低于历史最低的股价,则更新最低的估计;否则就计算当前股价与最低的股价间的利润是否大于了最大的利润,大于则更新
private static int maxFrofit(int[] prices){
int maxProfit = 0;
//最低股价
int minPrice = Integer.MAX_VALUE;
for (int i = 0; i < prices.length ; i++) {
//如果当前股价低于最低股价
if(prices[i] < minPrice){
minPrice = prices[i];
}else if(prices[i] - minPrice > maxProfit){ //判断最大的利润是否发生了改变
maxProfit = prices[i] - minPrice;
}
}
return maxProfit;
}
3.最大子序和
给定一个整数数组 nums
,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例:
输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
思路:连续和最大两个词联想到DP。这题和上一题类似,一个变量sum保存从到当前位置最大的子序列和,一个变量result保存全局的最大子序列和
当前位置到的最大子序和sum = max(nums[i], sum+nums[i]),即是加上当前位数值和不加二者之间的最大值;
然后,result更新为前面保存的result和当前的sum之间较大的那个
class Solution {
public int maxSubArray(int[] nums) {
int result = nums[0];
int sum = 0;
for(int i =0; i < nums.length ; i++){
sum = Math.max(nums[i],sum+nums[i]);
result =Math.max(result,sum);
}
return result;
}
}
4.打家劫舍
你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组,计算你在不触动警报装置的情况下,能够偷窃到的最高金额。
示例 1:
输入: [1,2,3,1]
输出: 4
解释: 偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。
偷窃到的最高金额 = 1 + 3 = 4 。
简单DP,
class Solution {
public int rob(int[] nums) {
if (nums==null || nums.length ==0){
return 0;
}
if (nums.length ==1){
return nums[0];
}
int[] dp = new int[nums.length];
dp[0] = nums[0];
if (nums[1] > nums[0]){
dp[1] = nums[1];
}else {
dp[1] = nums[0];
}
for (int i = 2; i < nums.length; i++) {
int notRob = dp[i-1];
int rob = dp[i-2]+nums[i];
dp[i] = notRob > rob ? notRob:rob;
}
return dp[nums.length-1];
}
}
偷或者不偷中选择大的那个。