leetcode 跳跃游戏(动态规划、单调栈、bfs)

一、(leetcode 55)给定一个非负整数数组,你最初位于数组的第一个位置。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
判断你是否能够到达最后一个位置。

思路:
记录在每个位置上,能到达的最大距离;
代码如下:

class Solution {
public:
    bool canJump(vector<int>& nums) {
        int index=0;
        for(int i=0;i<nums.size();i++){
            if(i>index){
                return false;
            }
            else{
                index=max(index,i+nums[i]);
            }
        }
        return true;
    }
};

二、(leetcode 45)给定一个非负整数数组,你最初位于数组的第一个位置。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
你的目标是使用最少的跳跃次数到达数组的最后一个位置。

思路:
同上一题,增加一个标记,记录跳跃次数
代码如下:

class Solution {
public:
    int jump(vector<int>& nums) {
        int index=0,end=0;
        int res=0;
        for(int i=0;i<nums.size()-1;i++){
            index=max(index,i+nums[i]);
            if(i==end){
                end=index;
                res++;
            }
        }
        return res;
    }
};

三、(leetcode 1306)这里有一个非负整数数组 arr,你最开始位于该数组的起始下标 start 处。当你位于下标 i 处时,你可以跳到 i + arr[i] 或者 i - arr[i]。
请你判断自己是否能够跳到对应元素值为 0 的 任一 下标处。
注意,不管是什么情况下,你都无法跳到数组之外。

代码如下:

class Solution {
public:
    bool dfs(vector<int>&arr,int index){
        if(index<0||index>=arr.size()||arr[index]==-1){
            return false;
        }
        if(arr[index]==0){
            return true;
        }
        int step=arr[index];
        arr[index]=-1;
        return dfs(arr,index+step)||dfs(arr,index-step);
    }
    bool canReach(vector<int>& arr, int start) {
        return dfs(arr,start);
    }
};

四、(leetcode 1345)给你一个整数数组 arr ,你一开始在数组的第一个元素处(下标为 0)。
每一步,你可以从下标 i 跳到下标:
i + 1 满足:i + 1 < arr.length
i - 1 满足:i - 1 >= 0
j 满足:arr[i] == arr[j] 且 i != j
请你返回到达数组最后一个元素的下标处所需的 最少操作次数 。
注意:任何时候你都不能跳到数组外面。

代码如下:

class Solution {
public:
    int minJumps(vector<int>& arr) {
        int n=arr.size();
        vector<int>step(n,INT_MAX);
        vector<int>visited(n,0);
        unordered_map<int,vector<int>>m;
        step[n-1]=0;
        queue<int>q;
        q.push(n-1);
        for(int i=0;i<n-1;i++){
            m[arr[i]].push_back(i);
        }
        while(!q.empty()){
            int u=q.front();
            q.pop();
            if(u-1>=0&&!visited[u-1]&&m.find(arr[u-1])!=m.end()){
                step[u-1]=min(step[u-1],step[u]+1);
                visited[u-1]=1;
                q.push(u-1);
            }
            if(u+1<n&&!visited[u+1]&&m.find(arr[u+1])!=m.end()){
                step[u+1]=min(step[u+1],step[u]+1);
                visited[u+1]=1;
                q.push(u+1);
            }
            if(m.find(arr[u])!=m.end()){
                for(int v:m[arr[u]]){
                    if(!visited[v]){
                        step[v]=min(step[v],step[u]+1);
                        visited[v]=1;
                        q.push(v);
                    }
                }
                m.erase(arr[u]);
            }
        }
        return step[0];
    }
};

五、(leetcode 1340)给你一个整数数组 arr 和一个整数 d 。每一步你可以从下标 i 跳到:
i + x ,其中 i + x < arr.length 且 0 < x <= d 。
i - x ,其中 i - x >= 0 且 0 < x <= d 。
除此以外,你从下标 i 跳到下标 j 需要满足:arr[i] > arr[j] 且 arr[i] > arr[k] ,其中下标 k 是所有 i 到 j 之间的数字(更正式的,min(i, j) < k < max(i, j))。
你可以选择数组的任意下标开始跳跃。请你返回你 最多 可以访问多少个下标。
请注意,任何时刻你都不能跳到数组的外面。

代码如下:

class Solution {
    vector<int>cnt;
public:
    void dfs(vector<int>&arr,int idx,int d,int n){
        if(cnt[idx]!=-1){
            return;
        }
        cnt[idx]=1;
        for(int i=idx-1;i>=0&&i>=idx-d&&arr[idx]>arr[i];i--){
            dfs(arr,i,d,n);
            cnt[idx]=max(cnt[idx],cnt[i]+1);
        }
        for(int i=idx+1;i<n&&i<=idx+d&&arr[idx]>arr[i];i++){
            dfs(arr,i,d,n);
            cnt[idx]=max(cnt[idx],cnt[i]+1);
        }
    }
    int maxJumps(vector<int>& arr, int d) {
        int n=arr.size();
        cnt.resize(n,-1);
        for(int i=0;i<n;i++){
            dfs(arr,i,d,n);
        }
        return *max_element(cnt.begin(),cnt.end());
    }
};

六、(leetcode 1696) 给你一个下标从 0 开始的整数数组 nums 和一个整数 k 。
一开始你在下标 0 处。每一步,你最多可以往前跳 k 步,但你不能跳出数组的边界。也就是说,你可以从下标 i 跳到 [i + 1, min(n - 1, i + k)] 包含 两个端点的任意位置。
你的目标是到达数组最后一个位置(下标为 n - 1 ),你的 得分 为经过的所有数字之和。
请你返回你能得到的 最大得分 。

思路:
单调栈

代码如下:

class Solution {
public:
    int maxResult(vector<int>& nums, int k) {
        if(nums.size()==1)  return nums[0];
        deque<pair<int,int>>q;
        q.push_back({nums[0],0});
        int res=0;
        for(int i=1;i<nums.size();i++){
            if(!q.empty()&&i-q.front().second>k){//判断是否过期
                q.pop_front();
            }
            res=q.front().first+nums[i];
            while(!q.empty()&&q.back().first<=res){//保持单调减
                q.pop_back();
            }
            q.push_back({res,i});//加入新元素
        }
        return res;
    }
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值