본문 바로가기
Computer Engineering

Codility - StoneWall

by En.Lee 2014. 10. 25.

https://codility.com/demo/results/demoFHGPX8-MAF/


Task description

Solution to this task can be found at our blog.

You are going to build a stone wall. The wall should be straight and N meters long, and its thickness should be constant; however, it should have different heights in different places. The height of the wall is specified by a zero-indexed array H of N positive integers. H[I] is the height of the wall from I to I+1 meters to the right of its left end. In particular, H[0] is the height of the wall's left end and H[N−1] is the height of the wall's right end.

The wall should be built of cuboid stone blocks (that is, all sides of such blocks are rectangular). Your task is to compute the minimum number of blocks needed to build the wall.

Write a function:

class Solution { public int solution(int[] H); }

that, given a zero-indexed array H of N positive integers specifying the height of the wall, returns the minimum number of blocks needed to build it.

For example, given array H containing N = 9 integers:

  H[0] = 8    H[1] = 8    H[2] = 5    
  H[3] = 7    H[4] = 9    H[5] = 8    
  H[6] = 7    H[7] = 4    H[8] = 8    

the function should return 7. The figure shows one possible arrangement of seven blocks.

Assume that:

  • N is an integer within the range [1..100,000];
  • each element of array H is an integer within the range [1..1,000,000,000].

Complexity:

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

Elements of input arrays can be modified.



--------------------------- 풀이 -----------------------------------------------------------

Code: 14:18:27 UTC, java, final, score: 100.00
// you can also use imports, for example:
import java.util.*;

// you can use System.out.println for debugging purposes, e.g.
// System.out.println("this is a debug message");

class Solution {
    public int solution(int[] H) {
        // write your code in Java SE 8
        /*
        문제:
        높이가 다른 블록이 있다. 입력되는 값은 다른 높이의 블록들이다.
        H[I] 는 블록의 높이를 말한다. I는 블록 왼쪽에서 오른쪽의 위치폭(?)이다.
        즉, H[0]은 왼쪽 끝, H[N-1] <- 끝! 은 오른쪽 끝을 말한다.
        (배열의 개수가 블록으로 채울 폭이라고 보면된다)
        최소한의 블록으로 벽을 쌓을 수 있는 최소한의 블록의 개수를 구해라.
        
        
        :: 이문제는 높이가 높은 블록으로 왼쪽부터 오른쪽까지 채우고 작은 블록을 그위에
        쌓는 방법을 프로그래밍화 한것이다 ::
        
        방법:
        배열에 포함한 높이를 비교해 높이가 큰쪽을 사용하면된다.
        즉, 이전 높이와 현재 높이를 비교해 현재 높이가 더 크면 계속 쌓아놓는다.
        만약 이전 높이에 비해 현재 높이가 작으면 높이가 큰 블록을 밑에 깔기위해
        꺼내서 쓴다. (현재 높이보다 큰놈이 없을때 까지 반복한다.)
        
        이후 왼쪽부터 오른쪽까지 블록을 다 채웠으면 남은 것들을 블록위에 쌓으면 된다.
        
        시나리오:
        1. 왼쪽 -> 오른쪽 까지 반복( H[0] ~ H[N-1] 까지)
        ---->> 2번 반복! (현재보다 높이가 낮은 이전 블록이 나올때까지!=> 현재보다 높은 블록은 벽을 만들어야한다.)
        2. 블록 저장소가 비어있지 않고 현재 블록의 높이가 이전보다 낮으면
        2-1. 블록 저장소에서 빼와서 벽을 만든다.
        3. 블록 저장소가 비어 있거나 현재 블록이 이전 블록보다 크면 블록저장소에 저장한다.
        4. 블록 저장소에서 빼와 사용한 블록과 저장소에 남은 블록들을 더한다.
        5. 더한값을 출력하면 사용된 블록이다.
        */
        
        int block_count = 0;
        Stack stack = new Stack<Integer>();
        for(int i=0; i < H.length; i++){
            while(!stack.empty() && (int)stack.peek() >H[i]){  // 현재 블록 높이 보다 이전것의 높이가 더 크다면 낮은게 나올때까지 계속 반복해서 저장소에서 빼 벽을 만든다.
                stack.pop();    // 블록 저장소에서 빼와 벽을 쌓는데 사용
                block_count++;  // 사용한 블록 개수 증가
            }
            
            if(stack.empty() || (int)stack.peek() < H[i]){ // 저장소가 비었거나, 현재 높이가 더 크면
                stack.push(H[i]);
            }
        }
//        System.out.println("block_count : " + block_count + " stack_size : " + stack.size());
        block_count += stack.size();    // 높이높은걸로 벽을 쌓고 그 위에 작은걸 올린다.
        
        return block_count;
    }
}
Analysis
Detected time complexity:
O(N)
testtimeresult
Example tests
example1.480 sOK
Correctness tests
simple11.476 sOK
simple21.476 sOK
simple31.476 sOK
simple41.468 sOK
boundary_cases1.496 sOK
Performance tests
medium11.580 sOK
medium21.548 sOK
medium31.344 sOK
medium41.496 sOK
large_piramid1.880 sOK
large_increasing_decreasing1.940 sOK
large_up_to_201.872 sOK
large_up_to_1001.900 sOK
large_max2.108 sOK