【跳跃游戏】判断能否到达最后——贪心算法
给定一个非负整数数组,你最初位于数组的第一个位置。数组中的每个元素代表你在该位置可以跳跃的最大长度。
判断你是否能够到达最后一个位置。
【法一】
//[2,3,1,1,4] [3,2,1,0,4]
//贪心算法
public boolean canJump(int[] nums){
int len = nums.length;
int maxlength = 0;//最远可达位置下标
for(int i=0;i<len;i++){
if(i>maxlength){//达到不了中间位置
return false;
}
//实时维护最远可以到达的位置(从0开始计算)
maxlength = Math.max(maxlength,i+nums[i]);
if(maxlength>=len-1){
return true;
}
}
return false;
}
【法二】
class Solution {
public boolean canJump(int[] nums) {
int len = nums.length;
int n=1;
for(int i=len-2;i>=0;i--){
if(nums[i]>=n){//n表示到达末尾的步数
n=1;//如果可以到达末尾,就截断,从头开始
}else{
n++;
}
if(n>1 && i==0){//到达首部还未找到
return false;
}
}
return true;
}
}
【跳跃游戏】最少要跳几次才到达最后
给定一个非负整数数组,你最初位于数组的第一个位置。数组中的每个元素代表你在该位置可以跳跃的最大长度。
你的目标是使用最少的跳跃次数到达数组的最后一个位置。
示例:
输入: [2,3,1,1,4]
输出: 2
解释: 跳到最后一个位置的最小跳跃数是 2。
从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。
class Solution {
public int jump(int[] nums) {
int n = nums.length;
if(nums.length==1) return 0;
int step = 0;
int start = 0;//起跳
int end = 0;//落点
while(end<n-1){
int nextReach = end;
for(int i = start;i<=end;i++){
nextReach = Math.max(nextReach,nums[i]+i);
}
start = end+1;
end = nextReach;
step++;
}
return step;
}
}
【爬楼梯】三步爬楼梯问题
三步问题。有个小孩正在上楼梯,楼梯有n阶台阶,小孩一次可以上1阶、2阶或3阶。实现一种方法,计算小孩有多少种上楼梯的方式。结果可能很大,你需要对结果模1000000007。
class Solution {
public int waysToStep(int n) {
if(n < 3) return n;
if(n == 3) return 4;
int[] dp = new int[n+1];
dp[1] = 1;
dp[2] = 2;
dp[3] = 4;
for(int i = 4; i <= n; i++){
dp[i] = (dp[i-1] + dp[i-2]) % 1000000007 + dp[i-3];
dp[i] = dp[i] % 1000000007;
}
return dp[n];
}
}
两步爬楼梯,不能连着爬两步
——即2 2不能连续,怎么做?
public class Solution {
public static void main(String[] args){
int n = 4;
System.out.println(waysToStep(n));
}
public static long waysToStep(int n){
if(n<3) return n;
long[] one = new long[n+1];//一步爬i阶的种数
long[] two = new long[n+1];//两步爬i阶的种数
one[1] = 1;one[2]=1;
two[2]=1;
for(int i=3;i<=n;i++){
one[i] = one[i-1] + two[i-1];
two[i] = one[i-2];
}
return one[n]+two[n];
}
}
【按摩师问题】数组间隔取值求最大和
一个有名的按摩师会收到源源不断的预约请求,每个预约都可以选择接或不接。在每次预约服务之间要有休息时间,因此她不能接受相邻的预约。给定一个预约请求序列,替按摩师找到最优的预约集合(总预约时间最长),返回总的分钟数。
class Solution {
public int massage(int[] nums) {
int len = nums.length;
int[] dp = new int[len];
if(len==0) return 0;
if(len==1) return nums[0];
dp[0] = nums[0];
dp[1] = Math.max(nums[0],nums[1]);
for(int i=2;i<len;i++){
dp[i] = Math.max(dp[i-1],dp[i-2]+nums[i]);
}
return dp[len-1];
}
}
【剪绳子】使得剪出来的长度乘积最大
剑指offer14 - I
给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]…k[m-1] 。请问 k[0]k[1]…*k[m-1] 可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
(1)动态规划DP
import java.util.*;
public class Main1{
public static void main(String[] args){
//长度为n的绳子,剪成整数长度的m段(n>1,m>1),问最大乘积是多少
int n = 10;//3+3+4=10,3*3*4=36
int[] dp = new int[n + 1];
//dp[0] = 0;
//dp[1] = 0;//n>1,m>1
dp[2] = 1;
dp[3] = 2;
for(int i=4;i<=n;i++){//剪成i段
for(int j=0;j<i;j++){
dp[i] = Math.max(dp[i],Math.max(dp[i-j] * j,(i-j)*j));
}
}
System.out.println(dp[n]);//36
}
}