【每日一题见微知著】Hash表+BFS—— 跳跃游戏 IV-Hard(今天这个难度对了)

本文介绍了如何使用哈希表和宽度优先搜索(BFS)解决LeetCode上的难题1345——跳跃游戏IV。通过预处理相同节点并记录下标,求得到达数组最后一个元素的最少操作次数。示例中,给出的数组需要跳跃3次才能到达末尾。
摘要由CSDN通过智能技术生成

⭐️寒假新坑——代码之狐的每日做题笔记

1345. 跳跃游戏 IV-Hard

题目描述:

给你一个整数数组 arr ,你一开始在数组的第一个元素处(下标为 0)。

每一步,你可以从下标 i 跳到下标:

  • i + 1 满足:i + 1 < arr.length
  • i - 1 满足:i - 1 >= 0
  • j 满足:arr[i] == arr[j]i != j

请你返回到达数组最后一个元素的下标处所需的 最少操作次数

注意:任何时候你都不能跳到数组外面。

示例 1:

输入:arr = [100,-23,-23,404,100,23,23,23,3,404]
输出:3
解释:那你需要跳跃 3 次,下标依次为 0 --> 4 --> 3 --> 9 。下标 9 为数组的最后一个元素的下标。

解题思路:

BFS(广度优先搜索):处理每步到达的节点,添加其下一步能够到达的未到达过的节点(由上述规则)

Hash表:预处理相同节点,记录相同节点的下标

细节:处理完之后清除能够到达的节点节约历遍时间——测试用例存在一个全是7,只有最后节点为11,由此我加入

//这里清楚该相同数字的下标队列,因为已经访问完(不然会超时)
                    list.clear();
代码实现(空间应该还可以优化):
class Solution {
    public int minJumps(int[] arr) {
        int l=arr.length;
        
        //保存每一个数字的多个下标,方便查询跳转
        Map<Integer,List<Integer>> map=new HashMap<>();
        //记录是否访问的数组,false表示未访问
        boolean[] visited=new boolean[l];

        //初始化统计,记录相同数字的下标,用《数字-下标链表》表示
        for(int i=0;i<l;i++){
            int mid=arr[i];
            if(map.get(mid)==null){
                List<Integer> list=new ArrayList<>();
                list.add(i);
                map.put(mid,list);
            }
            else{
                map.get(mid).add(i);
            }
        }

        //每次使用一个队列保存下一步能够到达的下标
        //使用两个队列方便计算步骤
        List<Integer> q1=new ArrayList<>();
        List<Integer> q2=new ArrayList<>();

        //初始点0
        q1.add(0);
        visited[0]=true;
        
        int step=0;

        if(l-1==0){
            return 0;
        }

        while(true){
            if(q1.size()!=0){
                //q中保存当前步到达的点,历遍将下一步到达的点放入另一个q
                for(int cur:q1){

                    //下标+1
                    if(cur+1<l&&!visited[cur+1]){
                        //判断是否是目标
                        if(cur+1==l-1){
                            return step+1;
                        }
                        q2.add(cur+1);
                        visited[cur+1]=true;
                    }

                    //下标-1
                    if(cur-1>0&&!visited[cur-1]){
                        //不可能为目标
                        q2.add(cur-1);
                        visited[cur-1]=true;
                    }

                    //相同数字跳转
                    List<Integer> list=map.get(arr[cur]);
                    for(int next:list){
                        if(next==l-1){
                            return step+1;
                        }
                        if(!visited[next]){
                            q2.add(next);
                            visited[next]=true;
                        }
                    }
                    //这里清楚该相同数字的下标队列,因为已经访问完(不然会超时)
                    list.clear();
                }
                q1.clear();
            }
            else{
                //同上
                for(int cur:q2){

                    if(cur==l-1){
                        return step;
                    }

                    if(cur+1<l&&!visited[cur+1]){
                        if(cur+1==l-1){
                            return step+1;
                        }
                        q1.add(cur+1);
                        visited[cur+1]=true;
                    }

                    if(cur-1>0&&!visited[cur-1]){
                        q1.add(cur-1);
                        visited[cur-1]=true;
                    }

                    List<Integer> list=map.get(arr[cur]);
                    for(int next:list){
                        if(next==l-1){
                            return step+1;
                        }
                        if(!visited[next]){
                            q1.add(next);
                            visited[next]=true;
                        }
                    }
                    list.clear();
                }
                q2.clear();
            }
            //步骤+1
            step++;
        }
    }
}

结尾

题目来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems

⭐️关注作者,带你刷题,从简单的算法题了解最常用的算法技能(寒假每日一题)
⭐️关注作者刷题——简单到进阶,让你不知不觉成为无情的刷题机器,有问题请私信

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

代码之狐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值