35

By given an array of integers, each element represents a building. For example: int buildings[] = {1, 4, 3, 2, 3, 1}.

If I drew the buildings horizontally with a brush, how many brush strike I would use?

I should write a function that returns the number of these brush strokes. For example 5.

enter image description here

I can do it easily on run time O(n^2), by using 2 loops.

  • The external loop running on the levels of each building (according to the highest building).

  • The inner loop is running on the array from 0 to n, and compares the difference of the height (0 or 1) between two near elements.

How can I do this in the O(n) time and O(n) space?

0

9 Answers 9

33

A brush stroke starts whenever the height increases going from left to right, and ends when it decreases. You only need to look at when it increases, because if you just count the starting points of each stroke you will have the stroke count. Instead of looping over the height levels in an inner loop, just subtract one height level from the previous to get the difference.

In pseudo-code:

int BrushCount(int[] buildings)
{
    int brushCount = 0;
    int prevHeight = 0;
    for(int i = 0; i < buildings.length; i++)
    {
        if(buildings[i] > prevHeight)
             brushCount = brushCount + (buildings[i] - prevHeight);
        prevHeight = buildings[i];
    }
    return brushCount;
}

Runs in O(n).

Sign up to request clarification or add additional context in comments.

2 Comments

Just a little nitpick - your pseudocode fails for the OP's two examples. Can you tell why?
The update to prevHeight needs to happen unconditionally, otherwise the algorithm is incortect whenever you need multiple brush strokes on one height.
4

A little code golf :) (Based on samgak's excellent explanation.)

const f = A => A.reduce((a,b,i,A) => a + Math.max(0, b - A[i-1]));

console.log(f([1, 4, 3, 2, 3, 1]))
console.log(f([4, 1, 2, 1, 2, 2]))

3 Comments

@Neil what makes mine not "actual?"
Code golf is about making code as short as possible. It's a fun game, but one that should never be used on code written for ones employer.
@Neil that's only if you're planning to win the round. I maintain my line is code golf, albeit not the shortest.
2

Counting from the end of the array use the last element as the initial value of the result, and compare the previous one with the current one.

If they are the same value then, the result increase one; if the previous one is smaller than the current one, do nothing; if the previous one is bigger than the current one then, result = result +previous-current

int i=sizeof buildings;
int t=buildings[i]; 
while(i>0){
  if(buildings[i-1]-buildings[i]>0) t+=(buildings[i-1]-buildings[i]);
  else if(buildings[i-1]-buildings[i]==0) ++t;
  --i;
}
return t;

Comments

2
public static int brushCount(int[] buildings)
{
    int count=0;
    for(int i=0; i<=buildings.length-1; i++){
        if((i+1)<(buildings.length)){
            if(buildings[i]>buildings[i+1]){
                count += buildings[i]-buildings[i+1];
            }
        }else{
            count += buildings[i];
        } 
    }
    return count;
}

Comments

1

You can easily see that we need a stack like approach to keep heights in increasing order and add the difference between top element and current element when our current value is less than top value.

Since we don't values before the top, we can just keep a variable for the top element.

#include <bits/stdc++.h>

using namespace std;
using ll = int64_t;

int solve(vector<int> v) {
    int brushes = 0, lastMax = 0;

    for (auto val: v) {
        if (val > lastMax) {
            brushes += lastMax - val;
        }
        lastMax = val;
    }

    brushes += lastMax;

    return brushes;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    vector<int> v1 {1, 4, 3, 2, 3, 1}, v2 {4, 1, 2, 1, 2, 2};
    cout << solve(v1) << ' ' << solve(v2) << endl; // 5 6
}

Comments

0

Kotlin version of @samgak's answer:

fun brush(nums: IntArray): Int {
    var c = 0
    var ph = 0
    
    nums.forEach {
        if (it > ph) c += (it - ph)
        ph = it
    }
    
    return c
}

Comments

0

Shortly java answer:

int BrushCount(int[] buildings) {
    int s=0,p=0;
    for(int x:buildings) s-=(x>p?p:x)-(p=x);
    return s;
}

1 Comment

is s supposed to add, not substract? it should be s+=
0

Scala version of @samgak's answer:

object Solution {
  def solution(a: Array[Int]): Int = {
    var brushCount = 0;
    var prevheight = 0;
    for (i <- a) {
      if (i > prevHeight) {
        brushCount = brushCount + - (i - prevHeight);
      }
      prevHeight = i;
    }
    return brushCount;
  }
}

Comments

0

This question is asking for help using C#, but also there is Scala, Kotlin, and C++ so there is a Python code.

def BrushCount(A):
    if not A:
        return 0

    total_strokes = 0
    max_height = 0

    for height in A:
        strokes_needed = max(0, height - max_height)
        total_strokes += strokes_needed
        max_height = max(max_height, height)

    return total_strokes

Goodluck!

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.