DP:跳跃游戏 + 爬楼梯(一步多阶)+按摩师(数组间隔取值求和)+剪绳子

【跳跃游戏】判断能否到达最后——贪心算法

给定一个非负整数数组,你最初位于数组的第一个位置。数组中的每个元素代表你在该位置可以跳跃的最大长度。
判断你是否能够到达最后一个位置。
在这里插入图片描述
【法一】

//[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
    }
}

(2)贪心算法

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值