【LeetCode 1274】矩形内の船舶の数

(この問題は、対話型の問題です。)

デカルト平面で表される海上に、各船は整数点に配置され、各整数点は、ほとんどの1隻の船に含まれていてもよいです。

あなたは機能してい  Sea.hasShips(topRight, bottomLeft) 引数と戻りのように2点を取り  true 長方形に少なくとも1隻の船が境界に含め、二つの点で表さ存在するときかつそのときのみ、と。

上部の右及び矩形の左下の角2点を与えられ、その矩形内に存在する船舶の数を戻します。その四角形の中で最も10隻の船があることが保証されています。

400回の以上の呼び出しを行うの提出をする  hasShips と判断されます  間違った回答をまた、裁判官を回避しようとあらゆるソリューションは失格になります。

 

例:

入力:
船舶= [1,1]、[2,2]、[3,3]、[5,5]、topRight = [4,4]、bottomLeft = [0,0] 
出力:3 
説明: [0,0]から[4,4]に、我々は、範囲内の3隻の船をカウントすることができます。

 

制約:

  • 入力時に  ships のみ、内部でマップを初期化するために与えられています。あなたは「目隠し」この問題を解決しなければなりません。言い換えれば、あなたは、特定の使用して答えを見つけなければなら  hasShips 知らなくても、APIを  ships 位置。
  • 0 <= bottomLeft[0] <= topRight[0] <= 1000
  • 0 <= bottomLeft[1] <= topRight[1] <= 1000

 

ここでは分割統治を適用。4つの等しい小さな領域に現在の探索領域を分割します。以下の基本ケースで再帰的にこれを行います。

1.現在の検索領域が有効でないか、それはそれで何の船を持っていない場合は、リターン0;

2.現在の検索領域は、単一の点、復帰1である場合。

 

Runtime: T(N) = 4*T(N/4) + O(N^0); a = 4 > b^d = 4^0 = 1; case 3 of the master method, T(N) = O(N^(loga / logb)) = O(N).

 

One implementation pitfall is that since you compute the middle point using: bottomLeft + (topRight - bottomLeft) / 2, when bottomLeft and topRight are off by 1, the middle point will be bottomLeft. To avoid non-ending recursion bug, recurse on (bottomLeft, middle point) and (middle point + 1, topRight). For example, if bottomLeft is (1, 1) and topRight is (2, 2), middle point will be (1, 1). Recurse on (bottomLeft, middle point) and (middle point + 1, topRight) leads to 2 base case(single point(1, 1) and (2,2)); However, recurse on (bottomLeft, middle point + 1) and (middle point, topRight) leads to recursing on the same region(1,1) and (2,2) again, causing stackoverflow.

 

Proof that this algorithm makes at most 400 hasShips calls. 

For simplicity, let's assume the upper bound is 1024 * 1024 instead of 1000 * 1000, if we can prove for 1024 * 1024 then certainly the 1000 * 1000 case meets this condition. 

At the top level, we make 4 hasShip calls. The next level we make at most 4 * 4 = 16 calls. Each search region has been reduced to 256 * 256. Starting from this level, since we know that there are at most 10 ships in total, we will recurse on at most 10 search regions, each recursion on each region makes 4 calls. So that is at most 10 * 4 calls each level down, until we reach the base case. 256 == 2^8, to reach the base case, 

2's power goes from 8 to 0, decreasing by 1 each level down. 8 * 40 + 4 + 16 = 340 < 400.

Q.E.D

 

 

/**
 * // This is Sea's API interface.
 * // You should not implement it, or speculate about its implementation
 * class Sea {
 *     public boolean hasShips(int[] topRight, int[] bottomLeft);
 * }
 */

class Solution {
    public int countShips(Sea sea, int[] topRight, int[] bottomLeft) {
        return divideAndConquer(sea, topRight, bottomLeft);
    }
    private int divideAndConquer(Sea sea, int[] topRight, int[] bottomLeft) {
        if(topRight[0] < bottomLeft[0] || topRight[1] < bottomLeft[1] || !sea.hasShips(topRight, bottomLeft)) {
            return 0;
        }
        if(topRight[0] == bottomLeft[0] && topRight[1] == bottomLeft[1]) {
            return 1;
        }
        int cnt = 0;
        int midX = bottomLeft[0] + (topRight[0] - bottomLeft[0]) / 2;
        int midY = bottomLeft[1] + (topRight[1] - bottomLeft[1]) / 2;
                
        cnt += divideAndConquer(sea, new int[]{midX, midY}, bottomLeft);
        cnt += divideAndConquer(sea, new int[]{topRight[0], midY}, new int[]{midX + 1, bottomLeft[1]});
        cnt += divideAndConquer(sea, new int[]{midX, topRight[1]}, new int[]{bottomLeft[0], midY + 1});
        cnt += divideAndConquer(sea, topRight, new int[]{midX + 1, midY + 1});
        return cnt;
    }
}

 

おすすめ

転載: www.cnblogs.com/lz87/p/11968618.html