使用最少的矩形覆盖“曼哈顿天际线”

时间:2018-08-01 07:49:59

标签: java arrays algorithm

我写信来解决下面提供的Codility问题,

您将要建造一堵石墙。墙应笔直且长N米,且厚度应恒定。但是,它在不同的地方应该有不同的高度。墙的高度由N个正整数组成的数组H指定。 H [I]是壁的高度,从壁I到左端右侧的I + 1米。特别地,H [0]是墙的左端的高度,H [N-1]是墙的右端的高度。

墙壁应由长方体的石块建造(即,这些块的所有侧面均为矩形)。您的任务是计算建造隔离墙所需的最小块数。

编写函数:

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

给定一个由N个正整数组成的数组H,该整数指定墙的高度,它返回建造墙所需的最小块数。

例如,给定的数组H包含N = 9个整数:

  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

该函数应返回7。该图显示了七个块的一种可能排列。

假设:

N是[1..100,000]范围内的整数; 数组H的每个元素都是[1..1,000,000,000]范围内的整数。 复杂度:

预期的最坏情况下的时间复杂度为O(N); 预期的最坏情况下的空间复杂度为O(N)(不计算输入参数所需的存储空间)。

enter image description here

我为所提供的问题写了一个解决方案。下面提供了算法和代码,

算法

i。设置块数= 1并从数组的第二个元素开始迭代

ii。如果当前深度与以前相同,请继续

iii。如果当前深度较高,则将其推入堆栈并增加计数

iv。如果当前深度较低,请继续弹出直到当前深度> = peek。然后,如果堆栈大小等于或大于0,则将块计数增加1

代码

public static int solution(int[] H) {

    Stack<Integer> stack = new Stack<>();

    stack.push(H[0]);
    int count = 1;

    int N = H.length;

    for (int i = 1; i < N; i++) {

        if (H[i] == stack.peek()) {
            continue;
        } else if (H[i] > stack.peek()) {
            stack.push(H[i]);
            count++;
        } else {

            while (!stack.isEmpty() && H[i] < stack.peek()) {
                stack.pop();
            }

            stack.push(H[i]);
            count++;
        }
    }

    return count;
}

该解决方案无法提供正确的答案,即使花了一些时间进行调试,我也找不到该错误。有人看到吗?

下面提供了测试集,答案是7(我得到8)。

    int[] H = new int[9];

    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;

谢谢。

8 个答案:

答案 0 :(得分:1)

如果仍然有人对此练习感兴趣,请分享我的Python解决方案(Codility中100%)

def solution(H):
    stack, count = [], 1
    for i in H:
        if stack:
            if i == stack[-1]:
                continue
            if i < stack[-1]:
                while stack and stack[-1] > i:
                    stack.pop()
            if stack:
                if i > stack[-1]:
                    count+=1
                    stack.append(i)
            else:
                count+=1
                stack.append(i)
        else:
            stack.append(i)
    return count

答案 1 :(得分:1)

Ruby 100%

def solution(h)
  h.inject([1, [h.first]]) do |(blocks, stack), n|
    next [blocks+1, stack.push(n)]    if stack.last < n
    stack.pop while stack.any? && stack.last > n
    next [blocks, stack] if stack.last == n

   [blocks+1, stack.push(n)]
  end.first
end

答案 2 :(得分:1)

  

Python解决方案

这是我的解决方案 Solution with steps details

Codility python 100%

def solution(H):
"""
Codility 100%
https://app.codility.com/demo/results/trainingQKD6JP-PHA/

Idea is to use stack concept
Compute the minimum number of blocks needed to build the wall.
To build the wall start taking blocks of height one by one.
We need to take care of -
 - the blocked should not be used again
 - this is done only up to blocks height is greater than current
 - why we are using last 8 height block if there is already 8 height block used in previous step?
    reason is 8 is not present in stack top


8,
 8,----- can not use because on stack top 8 is already there
  5,
   7,
    9,
     8,
      7,------ can not use because on stack top 7 is already there
       4,
        8,

This is just example with height, see steps of output for details
 skip8           skip7
            |           |
|           |   |       |
|       |   |   |       |
|       |   |   |       |
|   |   |   |   |       |
|   |   |   |   |   |   |
|   |   |   |   |   |   |
|   |   |   |   |   |   |
|   |   |   |   |   |   |

已用块-     8     5     7     9     8     4     8

"""

block_count = 0
# stack is used to hold height used to building and remove all the blocks from it,
#  if any of the block of stack is greater than current block(to be added for building)
stack = []
for height in H:
    print(" ")
    print("Current Height " + str(height))
    print("Current stack " + str(stack))
    # Remove all blocks that are bigger than current height, stack should not be empty
    while stack and stack[-1] > height:
        stack.pop()
    print("After remove bigger blocks than current height " + str(stack))

    # stack is not empty and top item of stack is equal to current height
    if stack and stack[-1] == height:
        # Already used this size of block
        print("Already used this size of block " + str(height))
        continue
    else:
        # new block is required, push it's size to the stack
        block_count += 1
        stack.append(height)
        print("Add this block.... " + str(height) + " Minimum Blocks " + str(block_count))

return block_count

答案 3 :(得分:1)

Java中的另一种。更简单,因为我假设高度> 0。

    public int solution(int[] hs) {
        int squares = 0;
        Stack<Integer> s = new Stack<>();
        s.push(0);

        for (int h: hs) {
            while (s.peek() > h) {
                s.pop();
            }
            if (s.peek() != h) {
                s.push(h);
                ++squares;
            }
        }

        return squares;
    }

答案 4 :(得分:0)

我发现了这个错误,尽管可以分享。原因是新高度小于peek值,我们将继续弹出实体。因此,如果堆栈不为空,则新高度将等于或高于堆栈窥视值。

如果新高度相同,则意味着我们已经为该高度添加了一个块,并且不会添加新块。情况需要一个条件

               if (!stack.isEmpty() && H[i] == stack.peek()) {
                    continue;
                }

下面提供的代码提供了100% score

enter image description here

public int solution(int[] H) {

        Stack<Integer> stack = new Stack<>();

        stack.push(H[0]);
        int count = 1;

        int N = H.length;

        for (int i = 1; i < N; i++) {

            if (H[i] == stack.peek()) {
                continue;
            } else if (H[i] > stack.peek()) {
                stack.push(H[i]);
                count++;
            } else {

                while (!stack.isEmpty() && H[i] < stack.peek()) {
                    stack.pop();
                }

                /*
                 * the new entity is either in same elevation or higher
                 * */

                /*
                * if in same elevation, we already added the block, so keep iterating
                * */
                if (!stack.isEmpty() && H[i] == stack.peek()) {
                    continue;
                }

                stack.push(H[i]);
                count++;
            }
        }

        return count;
    }

答案 5 :(得分:0)

在c#中(100%在Codility中)

public int solution(int[] H) {

        Stack<int> stack = new Stack<int>();

        stack.Push(H[0]);
        int count = 1;



        for (int i = 1; i < H.Length; i++)
        {

            if (H[i] == stack.Peek())
            {
                continue;
            }
            else if (H[i] > stack.Peek())
            {
                stack.Push(H[i]);
                count++;
            }
            else
            {

                while (!(stack.Count==0) && H[i] < stack.Peek())
                {
                    stack.Pop();
                }
            if (!(stack.Count==0) && H[i] == stack.Peek()) {
                continue;
            }


                stack.Push(H[i]);
                count++;
            }
        }

        return count;
}

答案 6 :(得分:0)

100%C ++的Codility

#include <stack>

int solution(vector<int> &H) {
    int cnt{0};
    std::stack<int> reusedStone;

    for (auto h : H) {
        if (reusedStone.empty() || (h > reusedStone.top())) {
            reusedStone.push(h); cnt++;
        } else if (h < reusedStone.top()) {
            while ((!reusedStone.empty()) && (h < reusedStone.top())) {
                reusedStone.pop();
            }
            if ((!reusedStone.empty()) && (h == reusedStone.top())) {
                continue;
            } else {
                reusedStone.push(h); cnt++;
            }
        }
    }

    return cnt;
}

答案 7 :(得分:0)

更简单的Java解决方案。

public int solution(int[] H) {
    //block count
    int count = 0;
    // stack is used to hold height used to building and remove all the blocks from it,
    // if any of the block of stack is greater than current block(is to be added for building)
    Deque<Integer> stack = new ArrayDeque<>();

    for (int a : H) {
        // Remove all blocks that are bigger than current height, stack should not be empty
        while (!stack.isEmpty() && a < stack.peek()) {
            stack.pop();
        }
        //new block is required, push it's size to the stack
        if (stack.isEmpty() || a > stack.peek()) {
            count++;
            stack.push(a);
        }

    }
    return count;
}