leetcode
leetcode 1051 ~ 1100
矩形内船只的数目

矩形内船只的数目

难度:

标签:

题目描述

代码结果

运行时间: 32 ms, 内存: 16.1 MB


// 使用Java Stream的题解代码和注释

/*
 * 题目思路:
 * 由于Java Stream更适用于处理集合和数据流,本题目更适合递归划分和直接调用hasShips方法。
 * 由于题目特性,不适合使用Stream进行解决,此处提供类似的递归划分思路。
 */

class Solution {
    public int countShips(Sea sea, int[] topRight, int[] bottomLeft) {
        // Stream不适合此问题的解法,依然使用递归
        if (topRight[0] < bottomLeft[0] || topRight[1] < bottomLeft[1]) {
            return 0;
        }
        if (!sea.hasShips(topRight, bottomLeft)) {
            return 0;
        }
        if (topRight[0] == bottomLeft[0] && topRight[1] == bottomLeft[1]) {
            return 1;
        }
        int midX = (topRight[0] + bottomLeft[0]) / 2;
        int midY = (topRight[1] + bottomLeft[1]) / 2;
        return countShips(sea, new int[]{midX, midY}, bottomLeft) +
               countShips(sea, topRight, new int[]{midX + 1, midY + 1}) +
               countShips(sea, new int[]{midX, topRight[1]}, new int[]{bottomLeft[0], midY + 1}) +
               countShips(sea, new int[]{topRight[0], midY}, new int[]{midX + 1, bottomLeft[1]});
    }
}

解释

方法:

此题解的思路基于二分搜索和递归的方法来确定矩形区域内是否包含船只。首先,如果 topRight 的坐标小于或等于 bottomLeft 的坐标,或者通过调用 API hasShips 发现当前矩形区域内没有船只,则直接返回 0。如果矩形区域缩小到一个点,即 topRight 和 bottomLeft 坐标相同,且该点有船只,则返回 1。否则,根据 x 轴或 y 轴的坐标是否相等来决定如何进一步划分区域。如果 x 坐标相同,则沿 y 轴划分;如果 y 坐标相同,则沿 x 轴划分。对每个子区域递归地调用 countShips 函数,并将结果相加得到总船只数。

时间复杂度:

O(logN * logM)

空间复杂度:

O(logN + logM)

代码细节讲解

🦆
在递归函数中,参数`claim`的作用是什么?如何影响`hasShips`方法的调用或递归逻辑?
在递归函数中,参数`claim`主要用于优化API调用,避免重复检测某些区域内是否有船。当`claim`为True时,表示调用者已确定该区域有船,因此不需要再次调用`hasShips`方法进行检测。这样可以减少API的调用次数,提高算法的效率。在逻辑上,如果上一次递归返回的结果是有船的(例如A不等于0),则下一次递归时将`claim`设置为True,直接认为该区域有船。
🦆
题解中提到,如果`topRight`的坐标小于`bottomLeft`的坐标,则返回0。这种情况下,具体是怎样的坐标比较导致判断区域无效?
如果`topRight`的x坐标小于`bottomLeft`的x坐标,或者`topRight`的y坐标小于`bottomLeft`的y坐标,这表明定义的矩形区域是不合理的。例如,矩形的上边界应该在下边界的上方,右边界应该在左边界的右侧。如果坐标设置错误,将导致区域无效,因此直接返回0,表示该区域内没有船只。
🦆
递归终止条件中,如果`topRight`和`bottomLeft`坐标相同且该点有船只,直接返回1。那么如果这个单点没有船只应该如何处理,是否有考虑到这种情况?
是的,这种情况已被考虑。如果`topRight`和`bottomLeft`坐标相同,即代表区域缩小到一个单点,此时会通过`hasShips`方法检查这个点是否有船。如果该点有船,则返回1;如果没有船,则`hasShips`方法会返回False,递归也随之返回0,表示这个点没有船只。
🦆
您如何确定何时沿x轴划分或沿y轴划分?是否有特定的规则或基于性能考虑的策略?
决定沿x轴还是y轴划分主要根据当前考虑的矩形的长和宽。通常选择将较长的维度进行划分,这样可以更均匀地分割区域,有助于更平衡的递归深度和可能更快地缩小搜索范围。如果x坐标相同(即矩形在x方向上的长度为0),则沿y轴划分;如果y坐标相同(即矩形在y方向上的长度为0),则沿x轴划分。如果两个坐标都不相同,一般选择较长的方向进行划分,以优化递归的效率。

相关问题