Microsoft Interview: transforming a matrix

后端 未结 5 1986
伪装坚强ぢ
伪装坚强ぢ 2021-01-30 11:37

Given a matrix of size n x m filled with 0\'s and 1\'s

e.g.:

1 1 0 1 0

0 0 0 0 0

0 1 0 0 0

1 0 1 1 0

if the matrix has 1 a

5条回答
  •  挽巷
    挽巷 (楼主)
    2021-01-30 12:22

    Here's another intuition that gives a clean and simple algorithm for solving the problem.

    An initial algorithm using O(n) space.

    For now, let's ignore the O(1) memory constraint. Suppose that you can use O(n) memory (if the matrix is m × n). That would make this problem a lot easier and we could use the following strategy:

    • Create an boolean array with one entry per column.
    • For each column, determine whether there are any 1's in the column and store that information in the appropriate array entry.
    • For each row, set that row to be all 1's if there are any 1's in the row.
    • For each column, set that column to be all 1's if the corresponding array entry is set.

    As an example, consider this array:

    1 1 0 1 0
    0 0 0 0 0
    0 1 0 0 0
    1 0 1 1 0
    

    We'd start off by creating and populating the auxiliary array, which can be done in time O(mn) by visiting each column one at a time. This is shown here:

    1 1 0 1 0
    0 0 0 0 0
    0 1 0 0 0
    1 0 1 1 0
    
    1 1 1 1 0  <--- aux array
    

    Next, we iterate across the rows and fill each one in if it contains any 1's. This gives this result:

    1 1 1 1 1
    0 0 0 0 0
    1 1 1 1 1
    1 1 1 1 1
    
    1 1 1 1 0  <--- aux array
    

    Finally, we fill in each column with 1's if the auxiliary array has a 1 in that position. This is shown here:

    1 1 1 1 1
    1 1 1 1 0
    1 1 1 1 1
    1 1 1 1 1
    
    1 1 1 1 0  <--- aux array
    

    So there's one problem: this uses O(n) space, which we don't have! So why even go down this route?

    A revised algorithm using O(1) space.

    It turns out that we can use a very cute trick to run this algorithm using O(1) space. We need a key observation: if every row contains at least one 1, then the entire matrix becomes 1's. We therefore start off by seeing if this is the case. If it is, great! We're done.

    Otherwise, there must be some row in the matrix that is all 0's. Since this row is all 0's, we know that in the "fill each row containing a 1 with 1's" step, the row won't be filled in. Therefore, we can use that row as our auxiliary array!

    Let's see this in action. Start off with this:

    1 1 0 1 0
    0 0 0 0 0
    0 1 0 0 0
    1 0 1 1 0
    

    Now, we can find a row with all 0's in it and use it as our auxiliary array:

    1 1 0 1 0
    0 0 0 0 0  <-- Aux array
    0 1 0 0 0
    1 0 1 1 0
    

    We now fill in the auxiliary array by looking at each column and marking which ones contain at least one 1:

    1 1 0 1 0
    1 1 1 1 0  <-- Aux array
    0 1 0 0 0
    1 0 1 1 0
    

    It's perfectly safe to fill in the 1's here because we know that they're going to get filled in anyway. Now, for each row that contains a 1, except for the auxiliary array row, we fill in those rows with 1's:

    1 1 1 1 1
    1 1 1 1 0  <-- Aux array
    1 1 1 1 1
    1 1 1 1 1
    

    We skip the auxiliary array because initially it was all 0's, so it wouldn't normally be filled. Finally, we fill in each column with a 1 in the auxiliary array with 1's, giving this final result:

    1 1 1 1 1
    1 1 1 1 0  <-- Aux array
    1 1 1 1 1 
    1 1 1 1 1
    

    Let's do another example. Consider this setup:

    1 0 0 0
    0 0 1 0
    0 0 0 0
    0 0 1 0
    

    We begin by finding a row that's all zeros, as shown here:

    1 0 0 0
    0 0 1 0
    0 0 0 0 <-- Aux array
    0 0 1 0
    

    Next, let's populate that row by marking columns containing a 1:

    1 0 0 0
    0 0 1 0
    1 0 1 0 <-- Aux array
    0 0 1 0
    

    Now, fill in all rows containing a 1:

    1 1 1 1
    1 1 1 1
    1 0 1 0 <-- Aux array
    1 1 1 1
    

    Next, fill in all columns containing a 1 in the aux array with 1's. This is already done here, and we have our result!

    As another example, consider this array:

    1 0 0
    0 0 1
    0 1 0
    

    Every row here contains at least one 1, so we just fill the matrix with ones and are done.

    Finally, let's try this example:

    0 0 0 0 0
    0 0 0 0 0
    0 1 0 0 0
    0 0 0 0 0
    0 0 0 1 0
    

    We have lots of choices for aux arrays, so let's pick the first row:

    0 0 0 0 0 <-- aux array
    0 0 0 0 0
    0 1 0 0 0
    0 0 0 0 0
    0 0 0 1 0
    

    Now, we fill in the aux array:

    0 1 0 1 0 <-- aux array
    0 0 0 0 0 
    0 1 0 0 0
    0 0 0 0 0
    0 0 0 1 0
    

    Now, we fill in the rows:

    0 1 0 1 0 <-- aux array
    0 0 0 0 0 
    1 1 1 1 1
    0 0 0 0 0
    1 1 1 1 1
    

    Now, we fill in the columns based on the aux array:

    0 1 0 1 0 <-- aux array
    0 1 0 1 0 
    1 1 1 1 1
    0 1 0 1 0
    1 1 1 1 1
    

    And we're done! The whole thing runs in O(mn) time because we

    • Do O(mn) work to find the aux array, and possibly O(mn) work immediately if one doesn't exist.
    • Do O(mn) work to fill in the aux array.
    • Do O(mn) work to fill in rows containing 1s.
    • Do O(mn) work to fill in columns containing 1s.

    Plus, it only uses O(1) space, since we just need to store the index of the aux array and enough variables to do loops over the matrix.

    EDIT: I have a Java implementation of this algorithm with comments describing it in detail available on my personal site. Enjoy!

    Hope this helps!

提交回复
热议问题