每日一题补题记录1

1345. 跳跃游戏 IV

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

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

i + 1 满足:i + 1 < arr.length
i - 1 满足:i - 1 >= 0
j 满足:arr[i] == arr[j] 且 i != j
请你返回到达数组最后一个元素的下标处所需的 最少操作次数 。

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


BFS,每一步都有三个跳法,注意每个值的等值跳只会跳一次,直接跳到最后一个等值位,然后不能再跳,否则会爆炸TLE!

小trick:逆序处理arr,确保处理等值跳时,会优先到达最后一个位置,略微优化一点

class Solution {
    public int minJumps(int[] arr) {
        int step=0,len=arr.length;
        if(len==0)return 0;
        //每一个元素和他对应的等值元素列表
        HashMap<Integer,List<Integer>>map=new HashMap<>();
        for (int i = len - 1; i >= 0; i--) { 
            List<Integer> list = map.getOrDefault(arr[i], new ArrayList<>());
            list.add(i);
            map.put(arr[i], list);
        }
        boolean[]visited=new boolean[len];
        Deque<Integer>queue=new LinkedList<>();
        queue.offer(0);
        while(!queue.isEmpty()){
            int size=queue.size();
            for(int i=0;i<size;i++){
                int cur=queue.poll();
                if(cur==len-1)return step;
                //左跳
                if(cur-1>=0&&!visited[cur-1]){
                    queue.offer(cur-1);
                    visited[cur-1]=true;
                }
                //右跳
                if(cur+1<len&&!visited[cur+1]){
                    queue.offer(cur+1);
                    visited[cur+1]=true;
                }
                //等值跳
                List<Integer> list = map.getOrDefault(arr[cur],new ArrayList<>());   
                for (int neigh : list) {
                    if (!visited[neigh]) {
                        queue.offer(neigh);
                        visited[neigh]=true;
                    }
                }
                map.remove(arr[cur]);   
            }
            step++;
        }
        return -1;
    }
}

2013. 检测正方形

给你一个在 X-Y 平面上的点构成的数据流。设计一个满足下述要求的算法:

添加 一个在数据流中的新点到某个数据结构中。可以添加 重复 的点,并会视作不同的点进行处理。
给你一个查询点,请你从数据结构中选出三个点,使这三个点和查询点一同构成一个 面积为正 的 轴对齐正方形 ,统计 满足该要求的方案数目。
轴对齐正方形 是一个正方形,除四条边长度相同外,还满足每条边都与 x-轴 或 y-轴 平行或垂直。

实现 DetectSquares 类:

DetectSquares() 使用空数据结构初始化对象
void add(int[] point) 向数据结构添加一个新的点 point = [x, y]
int count(int[] point) 统计按上述方式与点 point = [x, y] 共同构造 轴对齐正方形 的方案数。


我们要注意到,想要确定一个正方形,可以先寻找一个边,然后遍历其他点试试能否形成一个正方形,注意重复的点要乘法处理,想要根据“边”来寻找,我们可以用这样的哈希表来储存:使用双重哈希表,记录横坐标相同的所有点,记录方式是纵坐标和相同点的个数,这样我们想要寻找正方形时,找出所有横坐标相同的点,形成一条边,然后再遍历确定这条边是否可以构成正方形,然后返回答案即可

class DetectSquares {
    //双重哈希表,记录横坐标相同的所有点,记录方式是纵坐标和相同点的个数
    HashMap<Integer,HashMap<Integer,Integer>>map;
    public DetectSquares() {
        map=new HashMap<>();
    }

    public void add(int[] point) {
        int x=point[0],y=point[1];
        HashMap<Integer,Integer>mapx=map.getOrDefault(x,new HashMap<>());
        mapx.put(y,mapx.getOrDefault(y,0)+1);
        map.put(x, mapx);
    }
    
    public int count(int[] point) {
        int x = point[0], y = point[1];
        //要确保有横坐标相同的点才能构成正方形
        if(!map.containsKey(x))return 0;
        int ans = 0;
        HashMap<Integer,Integer>mapx=map.get(x);
        for(int newY:mapx.keySet()){
            if(newY==y)continue;
            int numY=mapx.get(newY);
            for(int newX:map.keySet()){
                HashMap<Integer,Integer>mapNewX=map.get(newX);
                if(mapNewX.containsKey(y)&&mapNewX.containsKey(newY)){
                    ans+=numY*mapNewX.get(y)*mapNewX.get(newY);
                }
            }
        }
        return ans;
    }
}

 第一次提交错误,问题在什么地方呢?我TM直接懵逼,真的不懂啊!!!

后来想了下,我这样找的是根本就是长方形,还是得审题啊!我真是SB,枚举可能的另一个x值即可

class DetectSquares {
    //双重哈希表,记录横坐标相同的所有点,记录方式是纵坐标和相同点的个数
    HashMap<Integer,HashMap<Integer,Integer>>map;
    public DetectSquares() {
        map=new HashMap<>();
    }

    public void add(int[] point) {
        int x=point[0],y=point[1];
        HashMap<Integer,Integer>mapx=map.getOrDefault(x,new HashMap<>());
        mapx.put(y,mapx.getOrDefault(y,0)+1);
        map.put(x, mapx);
    }
    
    public int count(int[] point) {
        int x = point[0], y = point[1];
        //要确保有横坐标相同的点才能构成正方形
        if(!map.containsKey(x))return 0;
        int ans = 0;
        //所有横坐标相同的点构成的集合,据此可以确定一条边和正方形边长
        HashMap<Integer,Integer>mapx=map.get(x);
        for(int newY:mapx.keySet()){
            if(newY==y)continue;
            //第二个点可取个数
            int num1=mapx.get(newY);
            //正方形边长
            int len = y - newY;
            //另一条边可以往左可以往右
            int[] newXs = new int[]{x + len, x - len};
            //枚举另一条边的个数
            for(int newX:newXs){
                if(!map.containsKey(newX))continue;
                HashMap<Integer,Integer>mapNewX=map.get(newX);
                if(mapNewX.containsKey(y)&&mapNewX.containsKey(newY)){
                    ans+=num1*mapNewX.get(y)*mapNewX.get(newY);
                }
            }
        }
        return ans;
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值