Water collected between towers

后端 未结 26 1151
无人共我
无人共我 2020-12-22 16:51

I recently came across an interview question asked by Amazon and I am not able to find an optimized algorithm to solve this question:

You are given an input array wh

26条回答
  •  情书的邮戳
    2020-12-22 17:21

    An intuitive solution for this problem is one in which you bound the problem and fill water based on the height of the left and right bounds.

    My solution:

    • Begin at the left, setting both bounds to be the 0th index.
    • Check and see if there is some kind of a trajectory (If you were to walk on top of these towers, would you ever go down and then back up again?) If that is the case, then you have found a right bound.
    • Now back track and fill the water accordingly (I simply added the water to the array values themselves as it makes the code a little cleaner, but this is obviously not required).
    • The punch line: If the left bounding tower height is greater than the right bounding tower height than you need to increment the right bound. The reason is because you might run into a higher tower and need to fill some more water. However, if the right tower is higher than the left tower then no more water can be added in your current sub-problem. Thus, you move your left bound to the right bound and continue.

    Here is an implementation in C#:

            int[] towers = {1,5,3,7,2};
    
            int currentMinimum = towers[0];
    
            bool rightBoundFound = false;
    
            int i = 0;
            int leftBoundIndex = 0;
            int rightBoundIndex = 0;
    
            int waterAdded = 0;
    
            while(i < towers.Length - 1)
            {
    
                currentMinimum = towers[i];
    
                if(towers[i] < currentMinimum)
                {
                    currentMinimum = towers[i];
                }
    
                if(towers[i + 1] > towers[i])
                {
                    rightBoundFound = true;
                    rightBoundIndex = i + 1;
                }
    
                if (rightBoundFound)
                {
    
                    for(int j = leftBoundIndex + 1; j < rightBoundIndex; j++)
                    {
    
                        int difference = 0;
    
                        if(towers[leftBoundIndex] < towers[rightBoundIndex])
                        {
                            difference = towers[leftBoundIndex] - towers[j];
                        }
                        else if(towers[leftBoundIndex] > towers[rightBoundIndex])
                        {
                            difference = towers[rightBoundIndex] - towers[j];
                        }
                        else
                        {
                            difference = towers[rightBoundIndex] - towers[j];
                        }
    
                        towers[j] += difference;
                        waterAdded += difference;
    
                    }
    
                    if (towers[leftBoundIndex] > towers[rightBoundIndex])
                    {
                        i = leftBoundIndex - 1;
                    }
                    else if (towers[rightBoundIndex] > towers[leftBoundIndex])
                    {
                        leftBoundIndex = rightBoundIndex;
                        i = rightBoundIndex - 1;
                    }
                    else
                    {
                        leftBoundIndex = rightBoundIndex;
                        i = rightBoundIndex - 1;
                    }
                    rightBoundFound = false;
    
                }
    
                i++;
    
            }
    

    I have no doubt that there are more optimal solutions. I am currently working on a single-pass optimization. There is also a very neat stack implementation of this problem, and it uses a similar idea of bounding.

提交回复
热议问题