Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Turning negative entries positive in a matrix by checking adjacent entries- only certain conversions allowed each pass, what's the time complexity?

I am given an (nxm) matrix of positive and negative integers.

The goal is to try and convert all negative numbers into positive ones, and if this is possible, return the number of passes of the matrix required to do this, otherwise return -1.

Here are the rules:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

  • You can only convert a negative number into a positive one, if the negative number has an adjacent (directly above, below, left or right) entry that is positive.
  • If you convert a number from negative to positive in a certain pass, you cannot then use this (recently) turned positive number to turn other negative numbers positive- at least for this pass.

I have written an accepted solution to the problem, but I can’t seem to work out the Time Complexity of the solution.

My solution:

  1. Create a Boolean matrix to mark the negative entries that have been turned positive in the current pass (we will reset this matrix after each pass)

  2. Iterate over all entries of the matrix

  3. For every negative number we stumble across check all 4 of its adjacent entries and see if there are any positive entries.
    If so, convert it to positive and mark it in the boolean matrix.

  4. Increment number of passes each time we iterate over the whole matrix.

  5. We are done when we iterate over the entire matrix and have not made a single change to it (i.e. conversion from negative to positive).

  6. If there are any negative entries left, return -1, otherwise return the number of passes.

I can’t seem to think of a worst case- any suggestions on the time complexity of this solution?
My initial thought are that it is O(n), where n is the size of the matrix.

For reference, here is my solution:

def minimumPassesOfMatrix(matrix):
    numberOfPasses = 0
    ChangesMade = True

    while ChangesMade:
        negToPosMarket = [[False for _ in range(len(matrix[0]))] for _ in range(len(matrix))]
        ChangesMade = False
        for row in range(len(matrix)):
            for col in range(len(matrix[0])):
                if matrix[row][col] < 0:
                    positiveAdjacent = checkAdjacentEntriesForPositive(matrix, row, col, negToPosMarket)
                    if positiveAdjacent:
                        matrix[row][col] *= -1
                        negToPosMarket[row][col] = True
                        ChangesMade = True
        if not ChangesMade:
            break
        numberOfPasses += 1

    if all(matrix[row][col] >= 0 for row in range(len(matrix)) for col in range(len(matrix[0]))):  #notebook double for loop list comp!
        return numberOfPasses

    print(matrix)

    return -1


def checkAdjacentEntriesForPositive(matrix, row, col, negToPosMarket):
    matrixHeight = len(matrix) - 1
    matrixWidth = len(matrix[0]) - 1

    if not OutOfBounds(row + 1, col, matrixHeight, matrixWidth) and not negToPosMarket[row + 1][col]:
        if matrix[row + 1][col] > 0:
            return True
    if not OutOfBounds(row - 1, col, matrixHeight, matrixWidth) and not negToPosMarket[row - 1][col]:
        if matrix[row - 1][col] > 0:
            return True
    if not OutOfBounds(row, col + 1, matrixHeight, matrixWidth) and not negToPosMarket[row][col + 1]:
        if matrix[row][col + 1] > 0:
            return True
    if not OutOfBounds(row, col - 1, matrixHeight, matrixWidth) and not negToPosMarket[row][col - 1]:
        if matrix[row][col - 1] > 0:
            return True

    return False


def OutOfBounds(row, col, matrixHeight, matrixWidth):
    return row < 0 or col < 0 or row > matrixHeight or col > matrixWidth

>Solution :

The worst case scenario would be a positive number at one corner of the matrix with everything else being negative. This will require n+m passes to flip the opposite corner. The total time would be (n+m)xnxm if you go through every position on each pass.

If you use a set of coordinates instead, this can be reduced to nxm

Place the coordinates of positive values in a set. At each pass convert their negative neighbours to positive and place these former negatives into a new set for the next pass. This way, you only process each item once.

Here’s a example in Python:

def makePos(matrix):
    m = len(matrix)
    n = len(matrix[0])
    plusCoords = {(r,c) for r,row in enumerate(matrix)
                        for c,val in enumerate(row)
                        if val>0} # initial set of + coordinates    
    passes = 0
    iterations = 0
    while plusCoords:      # more passes for new + coordinates
        passes += 1        # count passes
        nextCoords = set() # coordinates of new positives 
        for r,c in plusCoords: # go through this pass's coords
            iterations += 1
            for dr,dc in [(-1,0),(0,-1),(0,1),(1,0)]: # neigbors
                nr,nc = r+dr, c+dc
                if nr not in range(m): continue
                if nc not in range(n): continue
                if matrix[nr][nc] < 0:           # flip to positive
                    nextCoords.add((nr,nc))      # track flips
        for nr,nc in nextCoords:   
            matrix[nr][nc] *= -1         # update matrix
        plusCoords = nextCoords          # coords for next pass
    return passes or -1, iterations

M = [ [10,-1,-1,-1,-1],
      [-1,-1,-1,-1,-1],
      [-1,-1,-1,-1,-1]]

print(*makePos(M))  # 7 15  (7 passes,15 iterations)
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading