LEETCODE 1274. Number of Ships in a Rectangle 解题思路分析

题目大意:

矩阵内船只的数量

(此题是 交互式问题)

在用笛卡尔坐标系表示的二维海平面上,有一些船。每一艘船都在一个整数点上,且每一个整数点最多只有 1 艘船。

有一个函数 Sea.hasShips(topRight, bottomLeft),输入参数为右上角和左下角两个点的坐标,当且仅当这两个点所表示的矩形区域(包含边界)内至少有一艘船时,这个函数才返回 true,否则返回 false。

给你矩形的右上角 topRight 和左下角 bottomLeft 的坐标,请你返回此矩形内船只的数目。题目保证矩形内 至多只有 10 艘船。

调用函数 hasShips 超过 400 次 的提交将被判为 错误答案(Wrong Answer)。同时,任何尝试绕过评测系统的行为都将被取消比赛资格。

示例1:

输入:
 ships = [[1,1],[2,2],[3,3],[5,5]], topRight = [4,4], bottomLeft = [0,0]
输出:3
解释:在 [0,0] 到 [4,4] 的范围内总共有 3 艘船。

提示:

  • ships 数组只用于评测系统内部初始化。你无法得知 ships 的信息,所以只能通过调用 hasShips 接口来求解。
  • 0 <= bottomLeft[0] <= topRight[0] <= 1000
  • 0 <= bottomLeft[1] <= topRight[1] <= 1000

如果想查看本题目是哪家公司的面试题,请参考以下免费链接: https://leetcode.jp/problemdetail.php?id=1274

解题思路分析:

本题如果采用暴力解,需要查看每一个点上是否有船只,这样最多需要查询1000乘以1000次,肯定超过题目要求的最多查询次数。因此我们可以考虑采用二分查找的思路,由于是2位数组,因此二分需要将当前区域分成四个部分,以中心点为二分中心,分成左上,左下,右上和右下4部分,分别查看四个区域内是否有船只,如果没有,该区域内则不需要再次划分。反之如果存在船只,这需要继续二分,直到将区域分成1个点为止。不断二分的过程实际上是递归操作。每一层递归返回当前区域内船只的总数量,而当前区域内的总数量是4个部分船只数量的和。

实现代码:

public int countShips(Sea sea, int[] topRight, int[] bottomLeft) {
    // 如果当前区域为一个点,那么当前区域如果有船只,返回1,反之返回0
    if(topRight[0]==bottomLeft[0] && topRight[1]==bottomLeft[1]){
        return sea.hasShips(topRight, bottomLeft)?1:0;
    }
    // 如果当前区间不合理,返回0
    if(bottomLeft[0]>topRight[0] || bottomLeft[1]>topRight[1]){
        return 0;
    }
    // 当前区域中心横坐标
    int midX=(topRight[0]+bottomLeft[0])/2;
    // 当前区域中心纵坐标
    int midY=(topRight[1]+bottomLeft[1])/2;
    int res=0; // 返回结果
    // 如果左上区域存在船只,递归继续二分
    if(sea.hasShips(new int[]{midX,topRight[1]},new int[]{bottomLeft[0],midY+1})){
        res+=countShips(sea, new int[]{midX, topRight[1]}, 
             new int[]{bottomLeft[0],midY+1});
    }
    // 如果右上区域存在船只,递归继续二分
    if(sea.hasShips(topRight, new int[]{midX+1,midY+1})){
        res+=countShips(sea, topRight, new int[]{midX+1,midY+1});
    }
    // 如果右上区域存在船只,递归继续二分
    if(sea.hasShips(new int[]{midX,midY}, bottomLeft)){
        res+=countShips(sea, new int[]{midX,midY}, bottomLeft);
    }
    // 如果右下区域存在船只,递归继续二分
    if(sea.hasShips(new int[]{topRight[0],midY},new int[]{midX+1,bottomLeft[1]})){
        res+=countShips(sea, new int[]{topRight[0],midY}, 
             new int[]{midX+1,bottomLeft[1]});
    }
    return res;
}

本题解法执行时间为1ms。

Runtime: 1 ms, faster than 65.08% of Java online submissions for Number of Ships in a Rectangle.

Memory Usage: 27.6 MB, less than 100.00% of Java online submissions for Number of Ships in a Rectangle.

本网站文章均为原创内容,并可随意转载,但请标明本文链接
如有任何疑问可在文章底部留言。为了防止恶意评论,本博客现已开启留言审核功能。但是博主会在后台第一时间看到您的留言,并会在第一时间对您的留言进行回复!欢迎交流!
本文链接: https://leetcode.jp/leetcode-1274-number-of-ships-in-a-rectangle-解题思路分析/
此条目发表在leetcode分类目录,贴了, , 标签。将固定链接加入收藏夹。

发表评论

您的电子邮箱地址不会被公开。