【LeetCode周赛】第362场周赛

与车相交的点 简单

给你一个下标从 0 开始的二维整数数组 nums 表示汽车停放在数轴上的坐标。对于任意下标inums[i] = [starti, endi] ,其中 starti 是第i辆车的起点,endi是第 i辆车的终点。

返回数轴上被车 任意部分 覆盖的整数点的数目。

示例 1:

输入:nums = [[3,6],[1,5],[4,7]]
输出:7
解释:从 1 到 7 的所有点都至少与一辆车相交,因此答案为 7 。

示例 2:

输入:nums = [[1,3],[5,8]]
输出:7
解释:1、2、3、5、6、7、8 共计 7 个点满足至少与一辆车相交,因此答案为 7 。

提示:

  • 1 <= nums.length <= 100
  • nums[i].length == 2
  • 1 <= starti <= endi <= 100

分析: 因为数据较小,因此我直接进行了模拟。初始化一个全为0的数组,两层循环,遍历nums,紧接着再从start遍历至end,数组中对应下标的值+1。最终结果为数组中值>0的个数:
代码:

class Solution {
public:
    int numberOfPoints(vector<vector<int>>& nums) {
        vector<int> v(150,0);int ans=0;
        for(int i=0;i<nums.size();i++){
            for(int j=nums[i][0];j<=nums[i][1];j++){
                v[j]++;
            }
        }
        for(int i=0;i<v.size();i++){
            if(v[i]!=0) ans++;
        }
        return ans;
    }
};

优化: 可以利用差分数组思想,将start~end范围内的值均递增,最后统计前缀和中>0的数量。

class Solution {
public:
    int numberOfPoints(vector<vector<int>>& nums) {
        int v[105],ans=0,tmp=0;
        memset(v,0,sizeof(v));
        for(auto num : nums){
            v[num[0]]++;
            v[num[1]+1]--;
        }
        for(int n : v){
            if(tmp+n>0) ans++;
            tmp+=n;
        }
        return ans;
    }
};

判断能否在给定时间到达单元格 中等

给你四个整数 sxsyfxfy 以及一个 非负整数 t

在一个无限的二维网格中,你从单元格 (sx, sy) 开始出发。每一秒,你 必须 移动到任一与之前所处单元格相邻的单元格中。

如果你能在 恰好 t 秒 后到达单元格 (fx, fy) ,返回 true ;否则,返回 false

单元格的 相邻单元格 是指该单元格周围与其至少共享一个角的 8 个单元格。你可以多次访问同一个单元格。
示例 1
在这里插入图片描述

输入:sx = 2, sy = 4, fx = 7, fy = 7, t = 6
输出:true
解释:从单元格 (2, 4) 开始出发,穿过上图标注的单元格,可以在恰好 6 秒后到达单元格 (7, 7) 。

示例 2:
在这里插入图片描述

输入:sx = 3, sy = 1, fx = 7, fy = 3, t = 3
输出:false
解释:从单元格 (3, 1) 开始出发,穿过上图标注的单元格,至少需要 4 秒后到达单元格 (7, 3) 。 因此,无法在 3 秒后到达单元格 (7, 3) 。

提示:

  • 1 <= sx, sy, fx, fy <= 109
  • 0 <= t <= 109

分析: 每一个单元格都能有8个方向能走,因此从起点到终点最小的距离为: s t e p = m a x ( a b s ( f x − s x ) , a b s ( f y − s y ) ) step = max(abs(fx-sx), abs(fy-sy)) step=max(abs(fxsx),abs(fysy)),因此只需要 t > = s t e p t>=step t>=step即可。
但有个坑,当起点终点重叠时,t不能为1.

代码: (我第一次写时,没有想到最小步数的直接计算方法)

class Solution {
public:
    bool isReachableAtTime(int sx, int sy, int fx, int fy, int t) {
        if(fx==sx&&sy==fy&&t==1) return false;
        int a = min(abs(fx-sx), abs(fy-sy));
        int b = max(abs(fx-sx), abs(fy-sy))-a;
        if(t<a+b)
            return false;
        else
            return true;
    }
};

将石头分散到网格图的最少移动次数 中等

给你一个大小为 3 * 3 ,下标从 0 开始的二维整数矩阵 grid ,分别表示每一个格子里石头的数目。网格图中总共恰好有 9 个石头,一个格子里可能会有 多个 石头。

每一次操作中,你可以将一个石头从它当前所在格子移动到一个至少有一条公共边的相邻格子。

请你返回每个格子恰好有一个石头的 最少移动次数 。

示例 1:
在这里插入图片描述

输入:grid = [[1,1,0],[1,1,1],[1,2,1]]
输出:3
解释:让每个格子都有一个石头的一个操作序列为:
1 -将一个石头从格子 (2,1) 移动到 (2,2) 。
2 - 将一个石头从格子 (2,2) 移动到 (1,2) 。
3 - 将一个石头从格子(1,2) 移动到 (0,2) 。
总共需要 3 次操作让每个格子都有一个石头。 让每个格子都有一个石头的最少操作次数为 3 。

示例 2:
在这里插入图片描述

输入:grid = [[1,3,0],[1,0,0],[1,0,3]]
输出:4
解释:让每个格子都有一个石头的一个操作序列为:
1 - 将一个石头从格子 (0,1) 移动到 (0,2) 。
2 - 将一个石头从格子 (0,1) 移动到 (1,1) 。
3 - 将一个石头从格子(2,2) 移动到 (1,2) 。 4 - 将一个石头从格子 (2,2) 移动到 (2,1) 。
总共需要 4 次操作让每个格子都有一个石头。 让每个格子都有一个石头的最少操作次数为 4 。

提示:

  • grid.length == grid[i].length == 3
  • 0 <= grid[i][j] <= 9
  • grid 中元素之和为 9

分析: 比赛过程中,我使用的方法是模拟,但没有考虑到从哪个格子移动石子,对于整体移动次数有影响。
结束后,采取DFS进行搜索,结果超时!
最终根据题解,将石子为0,石子>1的格子分别保存,然后进行搜索。

代码:

class Solution {
public:
    int ans=1e4;

    void search(vector<vector<int>>& em,vector<vector<int>>& mo, int step,int index){
        if(index==em.size()){
            if(ans>step){ans=step;return ;}
        }
        if(step>=ans) return ;
        for(int j=0;j<mo.size();j++){
            if(mo[j][2]>1){
                mo[j][2]--;
                search(em, mo, step+abs(em[index][0]-mo[j][0])+abs(em[index][1]-mo[j][1]) ,index+1);
                mo[j][2]++;
            }
        }

    }

    int minimumMoves(vector<vector<int>>& grid) {
        vector<vector<int>> em;
        vector<vector<int>> mo;
        for(int i=0;i<3;i++){
            for(int j=0;j<3;j++){
                if(grid[i][j]==0) em.push_back({i,j});
                else if(grid[i][j]>1) mo.push_back({i,j,grid[i][j]});
            }
        }
        search(em, mo, 0, 0);
        return ans;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值