找实习之从0开始的后端学习日记【8.5】

leetcode

55. 跳跃游戏

给定一个非负整数数组 nums ,你最初位于数组的 第一个下标 。

数组中的每个元素代表你在该位置可以跳跃的最大长度。

判断你是否能够到达最后一个下标。

示例 1:

输入:nums = [2,3,1,1,4]
输出:true
解释:可以先跳 1 步,从下标 0 到达下标 1, 然后再从下标 1 跳 3 步到达最后一个下标。

示例 2:

输入:nums = [3,2,1,0,4]
输出:false
解释:无论怎样,总会到达下标为 3 的位置。但该下标的最大跳跃长度是 0 , 所以永远不可能到达最后一个下标。

提示:

1 <= nums.length <= 3 * 104
0 <= nums[i] <= 105

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/jump-game
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

本人想法

本题我递推出状态转移方程后用的循环。
在这里插入图片描述

class Solution {
    public boolean canJump(int[] nums) {
        boolean[] F = new boolean[nums.length];
        F[nums.length-1]=true;
        for(int i = nums.length -1;i>=0;i--){
            //从后往前
            int j = 0;
            while(j<=nums[i]){
                if(i+j<nums.length && F[i+j] ){
                    F[i]=true;
                    break;
                }
                j++;
            }
        }
        return F[0];
    }
}

跑出来速度就超过3%,我就想优化一下。设i是离0最近的true,那在此时记下一个量j=0,每次往前走一个就j++,如果当前nums[i-j]>=j就证明i-j可以走到i,就可以把i-j也置为true,也就是把i-j当成新的i,并重新令j=0。最后看一轮走完i最后是不是0,是的话就说明0true也就是可以走到
在这里插入图片描述

class Solution {
    public boolean canJump(int[] nums) {
    // boolean ret = false;
    int n = nums.length;
    int i = n-1;
    int j = 0;
    while(true){
        j++;

        if(i-j<0){
            break;
        }
        else if(nums[i-j]>=j){
            i = i-j;
            j=0;
        }
    }
    return i==0;
    }
}

在这里插入图片描述
因为就走了一趟,时间复杂度应该为O(N),空间复杂度为O(1)。

官方题解

官方直接给出了贪心方法(呃呃因为在动态规划题目里就先入为主了,虽然优化后的方法有贪心的思想。),直接遍历一遍,记录一个量最多能到达的距离:rightmost,每次都取rightmosti + nums[i]的最大值。好机智。时空复杂度和我相同,也是时间复杂度 O ( N ) O(N) O(N),空间复杂度 O ( 1 ) O(1) O(1)。学习学习。

public class Solution {
    public boolean canJump(int[] nums) {
        int n = nums.length;
        int rightmost = 0;
        for (int i = 0; i < n; ++i) {
            if (i <= rightmost) {
                rightmost = Math.max(rightmost, i + nums[i]);
                if (rightmost >= n - 1) {
                    return true;
                }
            }
        }
        return false;
    }
}

作者:LeetCode-Solution
链接:https://leetcode.cn/problems/jump-game/solution/tiao-yue-you-xi-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

45. 跳跃游戏 II

给你一个非负整数数组 nums ,你最初位于数组的第一个位置。

数组中的每个元素代表你在该位置可以跳跃的最大长度。

你的目标是使用最少的跳跃次数到达数组的最后一个位置。

假设你总是可以到达数组的最后一个位置。

示例 1:

输入: nums = [2,3,1,1,4]
输出: 2
解释: 跳到最后一个位置的最小跳跃数是 2。
     从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。

示例 2:

输入: nums = [2,3,0,1,4]
输出: 2

提示:

1 <= nums.length <= 104
0 <= nums[i] <= 1000

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/jump-game-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

我的思路

方案一

设F[i]是从0→i的最小步数。不能到达则置为n。初始F均为n;
F ( 0 ) = 0 F(0)=0 F(0)=0
F ( j ) = 1 , f o r    j    f r o m    1    t o    n u m s [ 0 ] F(j)=1, for \ \ j\ \ from\ \ 1 \ \ to \ \ nums[0] F(j)=1,for  j  from  1  to  nums[0]
👉对每个i F ( j ) = m i n { F ( j ) , F ( i ) + 1 } , f o r    j    f r o m    i    t o    i + n u m s [ i ] F(j) = min\{F(j), F(i)+1\}, for \ \ j \ \ from \ \ i \ \ to \ \ i + nums[i] F(j)=min{F(j),F(i)+1},for  j  from  i  to  i+nums[i]
i作为0n-1的索引,j对每个i都从0nums[i],以i为起点往后走j个,走过的都能从i1步就到达,所以将其F[j]置为F(i)+1F(j)自己的最小值。F[j]初始化为n

为了便于理解 写了个例子
在这里插入图片描述
显然这是会重复访问变量的。而且显然F(i)一旦写下后(除了初始化为n)就会最小,不可能再改,但是用这个方法会被重复访问到,然后进行min的判断操作。。
所以优化一下:
在这里插入图片描述

代码

class Solution {

    public int jump(int[] nums) {
        int n = nums.length;
        int[] F = new int[n];
        F[0]=0;
        if(n==1)return 0;
        F[1]=nums[0];
        if(F[1]>=n-1){return 1;}
        for(int i = 2;i<n;i++){
            F[i]=sub(nums,F[i-2],F[i-1]);
            if(F[i]>=n-1){return i;}
        }
        return n-1;
    }
    public int sub(int[] nums,int start,int end){//[start,end]区间
        int maxStep = 0;
        for(int j = start;j<end+1;j++){
            maxStep = Math.max(maxStep,j+nums[j]);
        }
        return maxStep;
    }
}

在这里插入图片描述

官方题解

看了一下答案,使用贪心思想,每次往后走都选择能走得最远的那个点。之后走到那个 点 step+1,再从当前点往后走,。。。循环。。

等同于把我的start end也就是F[i-2],F[i-1]直接用两个变量end,maxPosition 记录了,相当于滚动数组的思想。(指代码上。总的来说设定、含义不太相同,但代码上基本相似。)由于相当于滚动数组,所以时间复杂度相同为O(n),其中 n 是数组长度。空间复杂度从O(n)变为O(1)。

class Solution {
    public int jump(int[] nums) {
        int length = nums.length;
        int end = 0;
        int maxPosition = 0; 
        int steps = 0;
        for (int i = 0; i < length - 1; i++) {
            maxPosition = Math.max(maxPosition, i + nums[i]); 
            if (i == end) {
                end = maxPosition;
                steps++;
            }
        }
        return steps;
    }
}

作者:LeetCode-Solution
链接:https://leetcode.cn/problems/jump-game-ii/solution/tiao-yue-you-xi-ii-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值