[codility]NailingPlanks

Task description

You are given two non-empty zero-indexed arrays A and B consisting of N integers. These arrays represent N planks. More precisely, A[K] is the start and B[K] the end of the K−th plank.

Next, you are given a non-empty zero-indexed array C consisting of M integers. This array represents M nails. More precisely, C[I] is the position where you can hammer in the I−th nail.

We say that a plank (A[K], B[K]) is nailed if there exists a nail C[I] such that A[K] ≤ C[I] ≤ B[K].

The goal is to find the minimum number of nails that must be used until all the planks are nailed. In other words, you should find a value J such that all planks will be nailed after using only the first J nails. More precisely, for every plank (A[K], B[K]) such that 0 ≤ K < N, there should exist a nail C[I] such that I < J and A[K] ≤ C[I] ≤ B[K].

For example, given arrays A, B such that:

    A[0] = 1    B[0] = 4
    A[1] = 4    B[1] = 5
    A[2] = 5    B[2] = 9
    A[3] = 8    B[3] = 10

four planks are represented: [1, 4], [4, 5], [5, 9] and [8, 10].

Given array C such that:

    C[0] = 4
    C[1] = 6
    C[2] = 7
    C[3] = 10
    C[4] = 2

if we use the following nails:

  • 0, then planks [1, 4] and [4, 5] will both be nailed.
  • 0, 1, then planks [1, 4], [4, 5] and [5, 9] will be nailed.
  • 0, 1, 2, then planks [1, 4], [4, 5] and [5, 9] will be nailed.
  • 0, 1, 2, 3, then all the planks will be nailed.

Thus, four is the minimum number of nails that, used sequentially, allow all the planks to be nailed.

Write a function:

int solution(vector<int> &A, vector<int> &B, vector<int> &C);

that, given two non-empty zero-indexed arrays A and B consisting of N integers and a non-empty zero-indexed array C consisting of M integers, returns the minimum number of nails that, used sequentially, allow all the planks to be nailed.

If it is not possible to nail all the planks, the function should return −1.

For example, given arrays A, B, C such that:

    A[0] = 1    B[0] = 4
    A[1] = 4    B[1] = 5
    A[2] = 5    B[2] = 9
    A[3] = 8    B[3] = 10

    C[0] = 4
    C[1] = 6
    C[2] = 7
    C[3] = 10
    C[4] = 2

the function should return 4, as explained above.

Assume that:

  • N and M are integers within the range [1..30,000];
  • each element of arrays A, B, C is an integer within the range [1..2*M];
  • A[K] ≤ B[K].

Complexity:

  • expected worst-case time complexity is O((N+M)*log(M));
  • expected worst-case space complexity is O(M), beyond input storage (not counting the storage required for input arguments).

Elements of input arrays can be modified.


// you can use includes, for example:
#include <algorithm>

// you can write to stdout for debugging purposes, e.g.
// cout << "this is a debug message" << endl;
bool check(vector<int> &A, vector<int> &B, vector<int> &C, vector<int> &prefix_count, int middle) {
    int m = C.size();
    int n = A.size();
    
    fill(prefix_count.begin(), prefix_count.end(), 0);
    for (int i = 0; i <= middle; i++) {
        prefix_count[C[i]]++;
    }
    for (int i = 1; i < prefix_count.size(); i++) {
        prefix_count[i] += prefix_count[i-1];
    }
    
    for (int i = 0; i < n; i++) {
        if(prefix_count[B[i]] - prefix_count[A[i]-1] == 0) {
            return false;
        }    
    }
    return true;
}

int solution(vector<int> &A, vector<int> &B, vector<int> &C) {
    // write your code in C++11
    int m = C.size();
    int left = 0;
    int right = m - 1;
    
    vector<int> prefix_count((m << 1) | 1, 0);
    int ret = -1;
    while (left <= right) {
        int middle = ((right - left) >> 1) + left;
        if (check(A, B, C, prefix_count, middle)) {
            right = middle - 1;
            ret = middle + 1;
        }
        else {
            left = middle + 1;
        }
    }
    
    return ret;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值