查找最低编号需要喷泉

时间:2019-07-27 18:35:36

标签: arrays

有一个从1到n的线性花园。在每个点都有一个喷泉。给定数组a [n]告知有关喷泉的信息,以使其范围为喷泉左侧的max(i-a [i],1)到喷泉右侧的min(i + a [i],n)。查找最低编号的喷泉需要激活,以便覆盖整个花园。  例如,如果n = 3并且a = {1,2,1},则第二个喷泉的范围为1到3。因此,仅需要一个喷泉。这里的喷泉在1到2的范围内       2处的喷泉的范围是1到3,3处的喷泉的范围是2到3 因此,只有喷泉2足以激活以覆盖整个花园。

6 个答案:

答案 0 :(得分:0)

  • 分配最强大的喷泉,使其覆盖1到2 *范围-1
  • 从花园中删除分配的喷泉和1至2 *范围-1
  • 递归

答案 1 :(得分:0)

我认为您正在寻找O(n)时间和O(n)空间之外的解决方案。

创建间隔数组以存储可以从当前索引覆盖的最右边的范围。

public int findMinActivatedFountain(int[] arr, int n) {
        int[] interval = new int[n];
        int count = 1;

        // At each index we'll store the max right possible from this index.
        for (int i = 1; i <= n; i++) {
            int left = Math.max(i - arr[i - 1], 1);
            int right = Math.min(i + arr[i - 1], n);

            interval[left - 1] = right;
        }

        int right = interval[0];
        int currMax = right;
        for (int i = 1; i < n; i++) {
            currMax = Math.max(currMax, interval[i]);

            // If the last fountain can cover only this point, then update with next fountain.
            if (i == right) {
                count++;
                right = currMax;
            }
        }
        return count;
    }

答案 2 :(得分:0)

  • 时间复杂度-O(n)
  • 将范围的上下限存储在数组中(下面的喷泉数组)
  • 叠一叠,选择所有需要的喷泉。最初的堆栈为空。
    rightLimit =0; 
    leftLimit = 0;
    for(i=0; i<n; i++){
        if(rightLimit> fountainArray[i].rightLimit){
            if(leftLimit<= fountainArray[i].leftLimit){
                fountainStack.pop();
                //similarly check left limit of the new fountain on top
                //keep popping elements till fountainArray[i].leftLimit is > leftLimit of 
                //fountain on top of stack
            }
            fountainStack.push(fountainArray[i]);
        }
    }
    return fountainStack.length();

答案 3 :(得分:0)

遍历所有喷泉并构造数组跳转:

jumps [i] = {在i处其范围的左边界的所有喷泉的最大范围}

for (int i = 1; i <= n; i++){
l = max(1, i - arr[i-1])
r = min(n, i + arr[i-1])
jumps[l] = max(jumps[l], r - l);
}

然后在跳转数组上应用跳转游戏II(https://leetcode.com/problems/jump-game-ii/)。 这需要O(n)时间

答案 4 :(得分:0)

public static int find(int arr[], int n){
for (int i = 1; i <= n; i++){
   int l = max(1, i - arr[i-1])
   int r = min(n, i + arr[i-1])
  jumps[l] = max(jumps[l], r - l);
}
int longest = jump(jumps);
if(arr.lenght ==  longest){
 return 0;    
}else{
  return arr.length-longest-1;
}
}


// get the minimum jump to reach
public static int jump(int[] A) {
int sc = 0;
int e = 0;
int max = 0;
for(int i=0; i<A.length-1; i++) {
    max = Math.max(max, i+A[i]);
    if( i == e ) {
        sc++;
        e = max;
    } 
}
return sc;
}

答案 5 :(得分:0)

拉维的答案是正确的,但是其中有一个小错误

// At each index we'll store the max right possible from this index.
    for (int i = 1; i <= n; i++) {
        int left = Math.max(i - arr[i - 1], 1);
        int right = Math.min(i + arr[i - 1], n);

        interval[left - 1] = right;
    }

此处应为interval[left-1] = max(interval[left-1],right), 我们应该以该点为起点存储所有范围的最大值。休息都没错。