Home > other >  How to solve time constraint with coding challenge
How to solve time constraint with coding challenge

Time:09-05

I was doing a coding test (for practice) that went something like this:

Input is a string with |'s and *'s.
E.g. **|*|*|**|***

Implement the function:
List<int> countItems(string line, List<int> startLocations, List<int> endLocations)

Count the number of * characters that are between an opening and closing pair of | characters.

Where the 2 locations are arrays with the start and end locations (indices) to consider withing the string line.

For example if line = *|*|* and startLocations = [1] and endLocations = [3] it means I need to check the substring *|*.
And since there is only 1 pipe, the result is zero.
The location values seemed to be 1-based and not 0-based for some reason.

If the range was 1 and 5, for example, the result would be 1 because there is only 1 * between pipes.

The code I came up with that did manage to solve about half the test cases is as follows:

List<int> countItems(string line, List<int> startLocations, List<int> endLocations)
{
    var results = new List<int>();
    
    if (String.IsNullOrWhiteSpace(line) || startLocations.Count == 0)
    {
        return results;
    }

    for (var i = 0; i < startLocations.Count; i  )
    {
        var startIndex = startLocations[i] - 1;
        var endIndex = endLocations[i] - 1;

        var start = false;
        var total = 0;
        var tempTotal = 0;

        for (var j = startIndex; j < endIndex; j  )
        {
            if (!start && line[j] == '|')
            {
                start = true;
                tempTotal = 0;
            }
            else if (start && line[j] == '*')
            {
                tempTotal  ;
            }
            else if (line[j] == '|')
            {
                total  = tempTotal;
                tempTotal = 0;
            }
        }

        if (line[endIndex] == '|')
        {
            total  = tempTotal;
        }

        results.Add(total);
    }

    return results;
}

All the test cases either passed or failed because it ran out of time.

The error said it exceeded a time of 3 seconds.

Now I couldn't see the actual data being passed into the tests, so I'm not able to test it more.

But I suspect the solution was some kind of temporary list or dictionary so as to only iterate over the string 1 time instead of many times as in my code.

I want to learn what kind of solution to use in cases like this, but not really sure if this is a common type of question where the solution has some kind of name or common concept.

I would appreciate any obvious pointers to solving this type of question or even links to similar programming challenges where I can practice more.

CodePudding user response:

In this case I think the best option would be to use stack theory. It is a variation of the parenthesis balancing problem. You can find more about it here Article parenthesis balancing problem

CodePudding user response:

I managed to redo the test and I found the answer and problem type.

This is a "plates between candles" type of problem.

I was trying to solve it myself but almost ran out of time and eventually just copy/pasted an answer I found.
This was a practice run, not an actual test or application.

This was the solution that worked... I'll be studying it to better understand it...

List<int> numberOfItems(string s, List<int> startIndices, List<int> endIndices)
{
    int q = startIndices.Count;
    int l = s.Length;

    for (var i = 0; i < startIndices.Count; i  )
    {
        startIndices[i]--;
        endIndices[i]--;
    }

    var ans = new List<int>();
    var prev = new int[l];
    var next = new int[l];
    var preSum = new int[l];

    int p = -1, nxt = -1;

    // calculating prev candle up to this index.
    for (int i = 0; i < l; i  )
    {

        if (s[i] == '|')
        {
            p = i;
        }
        prev[i] = p;
    }
    //Calculating next candle from this index.

    for (int i = l - 1; i >= 0; i--)
    {

        if (s[i] == '|')
        {
            nxt = i;
        }
        next[i] = nxt;
    }

    int c = 0;

    // calculating the number of stars between these indices.
    for (int i = 0; i < l; i  )
    {

        if (s[i] == '*')
        {
            c  ;
        }
        preSum[i] = c;
    }

    // calculating ans.
    for (int k = 0; k < q; k  )
    {

        int i = startIndices[k];
        int j = endIndices[k];

        int right = prev[j];// position of left candle.
        int left = next[i];// position of right candle.
                           //cout<<right<<left;

        if (left == -1 || right == -1 || left > right)
        {
            ans.Add(0);
        }
        else
        {
            ans.Add(preSum[right] - preSum[left]);
        }
    }
    return ans;
}
  • Related