Codility Lesson 12 - Nailing Planks


https://codility.com/programmers/lessons/12
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(int A[], int B[], int N, int C[], int M);
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.

https://codesolutiony.wordpress.com/2015/01/14/codility-12-2-nailingplanks/
    public int solution(int[] A, int[] B, int[] C) {
        int[][] posMap = new int[C.length][2];
        for (int i = 0; i < C.length; i++) {
            posMap[i][0] = C[i];
            posMap[i][1] = i;
        }
        Arrays.sort(posMap, new Comparator<int[]>(){
            public int compare(int[] a, int[] b) {
                return Integer.compare(a[0], b[0]);
            }
        });
        int result = 0;
        for (int i = 0; i < A.length; i++) {//find the earlist position that can nail each plank, and the max value for all planks is the result
            int tmp = findNail(A[i], B[i], posMap, result);
            if (tmp == -1 || tmp == A.length - 1) {
                return tmp == -1 ? tmp : tmp + 1;
            }
            result = Math.max(result, tmp);
        }
        return result + 1;
    }
     
    private int findNail(int plankStart, int plankEnd, int[][] posMap, int prePos) {
        int start = 0;
        int end = posMap.length - 1;
        int pos = -1;
        while (start <= end) {
            int mid = (start + end) / 2;
            if (posMap[mid][0] > plankEnd) {
                end = mid - 1;
            } else if (posMap[mid][0] < plankStart) {
                start = mid + 1;
            } else {
                pos = mid; //get the original position of the nail
                end = mid - 1;
            }
        }
        if (pos == -1) {
            return pos;
        }
        int result = posMap[pos][1];
        //find the smallest original position of nail that can nail the plank
        for (int i = pos + 1; i < posMap.length; i++) {
            if (posMap[i][0] > plankEnd) {
                break;
            }
            result = Math.min(result, posMap[i][1]);
            if (result <= prePos) {//very important, otherwise TLE
                return prePos;
            }
        }
        return result;
    }

https://github.com/jlhuang/codility-lessons/blob/master/lesson%2012%20:%20Binary%20search%20algorithm/NailingPlanks/Solution.java
    public int solution(int[] A, int[] B, int[] C) {
        // the main algorithm is that getting the minimal index of nails which
        // is needed to nail every plank by using the binary search
        int N = A.length;
        int M = C.length;
        // two dimension array to save the original index of array C
        int[][] sortedNail = new int[M][2];
        for (int i = 0; i < M; i++) {
            sortedNail[i][0] = C[i];
            sortedNail[i][1] = i;
        }
        // use the lambda expression to sort two dimension array
        Arrays.sort(sortedNail, (int x[], int y[]) -> x[0] - y[0]);
        int result = 0;
        for (int i = 0; i < N; i++) {
            result = getMinIndex(A[i], B[i], sortedNail, result);
            if (result == -1)
                return -1;
        }
        return result + 1;
    }
    // for each plank , we can use binary search to get the minimal index of the
    // sorted array of nails, and we should check the candidate nails to get the
    // minimal index of the original array of nails.
    public int getMinIndex(int startPlank, int endPlank, int[][] nail, int preIndex) {
        int min = 0;
        int max = nail.length - 1;
        int minIndex = -1;
        while (min <= max) {
            int mid = (min + max) / 2;
            if (nail[mid][0] < startPlank)
                min = mid + 1;
            else if (nail[mid][0] > endPlank)
                max = mid - 1;
            else {
                max = mid - 1;
                minIndex = mid;
            }
        }
        if (minIndex == -1)
            return -1;
        int minIndexOrigin = nail[minIndex][1];
        // this check is to get the minimal index of the original array of nails
        for (int i = minIndex; i < nail.length; i++) {
            if (nail[i][0] > endPlank)
                break;
            minIndexOrigin = Math.min(minIndexOrigin, nail[i][1]);
            // we need the maximal index of nails to nail every plank, so the
            // smaller index can be omitted
            if (minIndexOrigin <= preIndex)
                return preIndex;
        }
        return minIndexOrigin;
    }

https://github.com/acprimer/Codility/blob/master/src/Lesson12/NailingPlanks.java
    // https://codility.com/demo/results/demoNQZADS-QJU/
    // TLE
    public int solution(int[] A, int[] B, int[] C) {
        boolean[] vis = new boolean[A.length];
        int count = 0;
        for (int i = 0; i < C.length; i++) {
            for (int j = 0; j < A.length; j++) {
                if (!vis[j] && A[j] <= C[i] && C[i] <= B[j]) {
                    vis[j] = true;
                    count++;
                }
            }
            if (count >= A.length) return i + 1;
        }
        return -1;
    }
http://www.martinkysel.com/codility-nailingplanks-solution/
to-do: http://codesays.com/2014/solution-to-nailing-planks-by-codility/
http://blog.csdn.net/caopengcs/article/details/41834173
更快的算法,如果我们建立一个长度为2 * M的数组,每个位置表示该位置上钉子的最小编号(可能同一个位置有多个钉子,取编号最小的),没有钉子的位置值为无穷大。那么固定第i块木板的最小编号钉子,相当于[A[i],B[i]]区间的最小值。但是我们这个题实际上是求这些最小值的max,首先如果一个木板A的覆盖区间完全包含另外一个木板B,则实际上我们只考虑木板B即可。因为固定木板B同时能固定木板A,并且我们一定要固定木板B,即使A覆盖区间有更小的值,也无法改变最终取最大值的结果。
于是,我们可以建立一个数组plank[x]表示右端点为x的木板的最大左边界,没有木板的话,认为边界是0。我们从左到右遍历木板右边界,假设这之前(更左)的木板已经被固定了,已经固定的区间范围是[left,right) (右开区间),然后对当前这个木板,如果显然它的右边界更大(我们遍历右边界是按当增的顺序),如果该木板start <= left,则它已经被前面固定住了,不影响结果。否则,要求[start,end]之间的最大值。这个问题有点像滑动窗口最大值的问题。本质在于:我们不断查询最大值,每次查询的时候窗口的左边界和右有边界是单调递增的,于是我们可以动态更新窗口维护最大值。这个经典问题可以用单调队列实现,这也是把单调队列发挥到了极致。
结论: 查询窗口最大值的时候,如果窗口向右滑动的过程中,查询时左边界和右边界都是单增的,则可以使用单调队列解决。
时间复杂度 O(N + M)达到了线性。
const int inf = 2000000000;
int solution(vector<int> &A, vector<int> &B, vector<int> &C) {
    // write your code in C++98
    int m = C.size(), M = (m << 1) | 1;
    vector<int> nail(M, inf);
    for (int i = m - 1; i >= 0; --i) {
        nail[C[i]] = i;
    }
    vector<int> plank(M, 0);
    for (int i = 0; i < A.size(); ++i) {
        plank[B[i]] = max(plank[B[i]], A[i]);
    }
    int left = 0, right = 0, r = 0;
    deque<int> q;
    for (int i = 1; i < M; ++i) {
        if (plank[i] > left) {
            left = plank[i];
            while ((!q.empty()) && (q.front() < left)) {
                q.pop_front();
            }
            for (right = max(right, left); right <= i; ++right) {
                while ((!q.empty()) && (nail[q.back()] >= nail[right])) {
                    q.pop_back();
                }
                q.push_back(right);
            }
            r = max(r, nail[q.front()]);
            if (r >= inf) {
                return -1;
            }
        }
    }
    return r + 1;
}
http://codility-lessons.blogspot.com/2015/03/lesson-11-nailingplanks-nailing-planks.html

Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts