Microsoft Interview Question!

You are given a matrix of dimensions m*n where each cell in the matrix can have values 0,1 or 2 which has the following meaning :

0:empty cell

1:cells have fresh oranges

2:cells have rotten oranges

So we have to determine what is the minimum time required so that all the oranges will be rotten.A rotten orange at index [i,j] can rot other fresh orange at indexes [i+1,j] ,[i,j+1] ,[i-1,j] ,[i,j-1]. If it is impossible to rot every orange then simply return -1.

// Author :: Gaurav Ahirwar
#include<bits/stdc++.h>
#define FOR(i,n) for(int i=(0);i<(n);i++)
#define R 3
#define C 5
using namespace std;
typedef long long int ll;

bool isvalid(int i, int j) {
if(i < 0 || j < 0 || i >= R || j >= C) return false;
else return true;
}

struct ele {
int x;
int y;
};

bool isdelim(ele temp) {
if(temp.x == -1 && temp.y == -1) return true;
else return false;
}

bool checkall(int arr[][C]) {
FOR(i,R) FOR(j,C) if(arr[i][j] == 1) return true;
return false;
}

void solve(int arr[][C]) {

queue<ele> Q;
ele temp;
int ans = 0;

FOR(i,R) {
FOR(j,C) {
if(arr[i][j] == 2) {
temp.x = i;
temp.y = j;
Q.push(temp);
}
}
}

temp.x = -1;
temp.y = -1;
Q.push(temp);

while(!Q.empty()) {

bool flag = false;

while(!isdelim(Q.front())) {

temp = Q.front();

if(isvalid(temp.x+1, temp.y) && arr[temp.x+1][temp.y] == 1) {
if(!flag) ans++, flag = true;
arr[temp.x+1][temp.y] = 2;
temp.x++;
Q.push(temp);
temp.x--;
}

if(isvalid(temp.x-1, temp.y) && arr[temp.x-1][temp.y] == 1) {
if(!flag) ans++, flag = true;
arr[temp.x-1][temp.y] = 2;
temp.x--;
Q.push(temp);
temp.x++;
}

if(isvalid(temp.x, temp.y+1) && arr[temp.x][temp.y+1] == 1) {
if(!flag) ans++, flag = true;
arr[temp.x][temp.y+1] = 2;
temp.y++;
Q.push(temp);
temp.y--;
}

if(isvalid(temp.x, temp.y-1) && arr[temp.x][temp.y-1] == 1) {
if(!flag) ans++, flag = true;
arr[temp.x][temp.y-1] = 2;
temp.y--;
Q.push(temp);
}

Q.pop();
}

Q.pop();

if(!Q.empty()) {
temp.x = -1;
temp.y = -1;
Q.push(temp);
}
}

if(checkall(arr)) cout << "All Apples cannot rot\n";
else cout << "Time required for all apples to rot => " << ans << endl;
}

int main() {

int arr[][C] = { {2, 1, 0, 2, 1},
{1, 0, 1, 2, 1},
{1, 0, 0, 2, 1}};
solve(arr);
return 0;
}

Assuming that the rotten oranges rote the fresh oranges at the same time. i.e. concurrently.

You can do a BFS here. Just add all the rotten oranges (i,j) pair in a queue and start popping the elements from the queue and add a  (-1,-1) to mark that the one unit of time has been passed. Now check all four sides of that particular pair and if fresh oranges are present at that point make them rotten and add those points to the queue. If the cell is empty then do nothing and if the cell contains the rotten orange then also do nothing. So whenever you got a pair (-1,-1) increment time by 1 unit if in this interval some oranges becomes rotten. So when the queue becomes empty check if there is some fresh oranges left or not in the matrix. if yes return -1 else time.

Time complexity O(n*m)

Here's my solution to the problem in go. Any feedback is appreciated.

package main

import (
"fmt"
)

type inp2dArray [3][5]int

type element struct {
i, j int
}

type queue struct {
elements []*element
}

// IsEmpty(), Push(element) and Pop() implemented for queue

func main() {

arr := inp2dArray{
[5]int{2, 1, 0, 2, 1},
[5]int{1, 0, 1, 2, 1},
[5]int{1, 0, 0, 2, 1},
}

// arr := inp2dArray{
// [5]int{2, 1, 0, 2, 1},
// [5]int{0, 0, 1, 2, 1},
// [5]int{1, 0, 0, 2, 1},
// }

minTime := 0
minTime = minimumTimeToRotAllOranges(arr, formFreshQueue(arr), &minTime)
fmt.Println("Minimum time to rot all oranges :", minTime)

}

func formFreshQueue(arr inp2dArray) *queue {

q := new(queue)
for i := 0; i < 3; i++ {
for j := 0; j < 5; j++ {
if arr[i][j] == 1 {
el := &element{i, j}
q.Push(el)
}
}
}
return q
}

func isValid(i, j int) bool {
return i >= 0 && i < 3 && j >= 0 && j < 5
}

func minimumTimeToRotAllOranges(arr inp2dArray, freshQueue *queue, time *int) int {

*time++
toBeRotten := new(queue)
stillFresh := new(queue)
el := freshQueue.Pop()

for ; el != nil; el = freshQueue.Pop() {

i, j := el.i, el.j
if isValid(i-1, j) && arr[i-1][j] == 2 ||
isValid(i+1, j) && arr[i+1][j] == 2 ||
isValid(i, j-1) && arr[i][j-1] == 2 ||
isValid(i, j+1) && arr[i][j+1] == 2 {

toBeRotten.Push(el)
} else {

stillFresh.Push(el)
}
}
if stillFresh.IsEmpty() {
return *time
}

if toBeRotten.IsEmpty() {
return -1
} else {
el := toBeRotten.Pop()
for ; el != nil; el = toBeRotten.Pop() {
arr[el.i][el.j] = 2
}

return minimumTimeToRotAllOranges(arr, stillFresh, time)
}
}

edited Aug 23, 2015 by pritz

use the code tag..i would encourage more GO solutions

the code tag doesn't work for Go I suppose

select any language like C/C++..atleast it will be readable then

Selecting other languages doesnt work either. I formatted it myself

it looks good..

package main

import (
"fmt"
)

type inp2dArray [3][5]int

type element struct {
i, j int
}

type queue struct {
elements []*element
}

// IsEmpty(), Push(element) and Pop() implemented for queue

func main() {

arr := inp2dArray{
[5]int{2, 1, 0, 2, 1},
[5]int{1, 0, 1, 2, 1},
[5]int{1, 0, 0, 2, 1},
}

// arr := inp2dArray{
// [5]int{2, 1, 0, 2, 1},
// [5]int{0, 0, 1, 2, 1},
// [5]int{1, 0, 0, 2, 1},
// }

minTime := 0
minTime = minimumTimeToRotAllOranges(arr, formFreshQueue(arr), &minTime)
fmt.Println("Minimum time to rot all oranges :", minTime)

}

func formFreshQueue(arr inp2dArray) *queue {

q := new(queue)
for i := 0; i < 3; i++ {
for j := 0; j < 5; j++ {
if arr[i][j] == 1 {
el := &element{i, j}
q.Push(el)
}
}
}
return q
}

func isValid(i, j int) bool {
return i >= 0 && i < 3 && j >= 0 && j < 5
}

func minimumTimeToRotAllOranges(arr inp2dArray, freshQueue *queue, time *int) int {

*time++
toBeRotten := new(queue)
stillFresh := new(queue)
el := freshQueue.Pop()

for ; el != nil; el = freshQueue.Pop() {

i, j := el.i, el.j
if isValid(i-1, j) && arr[i-1][j] == 2 ||
isValid(i+1, j) && arr[i+1][j] == 2 ||
isValid(i, j-1) && arr[i][j-1] == 2 ||
isValid(i, j+1) && arr[i][j+1] == 2 {

toBeRotten.Push(el)
} else {

stillFresh.Push(el)
}
}
if stillFresh.IsEmpty() {
return *time
}

if toBeRotten.IsEmpty() {
return -1
} else {
el := toBeRotten.Pop()
for ; el != nil; el = toBeRotten.Pop() {
arr[el.i][el.j] = 2
}

return minimumTimeToRotAllOranges(arr, stillFresh, time)
}
}

#include<iostream.h>
#include<conio.h>
#include<process.h>
void main()
{
clrscr();
int i,j,m=3,n=5,flag=0;
int a[3][5]={{2,1,0,2,1},{1,0,1,2,1},{1,0,0,2,1}},p=0,b[15],c[15],count=0;
for(i=0;i<15;i++)
{b[i]=0;c[i]=0;}
while(1)
{
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
{
if(a[i][j]==2)
{
b[p]=i;
c[p]=j;
p++;
}
}
}
for(i=0;i<p;i++)
{
if(a[b[i]-1][c[i]]==1&&b[i]!=0)
{a[b[i]-1][c[i]]=2;flag=1;}
if(a[b[i]+1][c[i]]==1&&b[i]!=m-1)
{a[b[i]+1][c[i]]=2;flag=1;}
if(a[b[i]][c[i]-1]==1&&c[i]!=0)
{a[b[i]][c[i]-1]=2;flag=1;}
if(a[b[i]][c[i]+1]==1&&c[i]!=n-1)
{a[b[i]][c[i]+1]=2;flag=1;}
}
for(i=0;i<p;i++)
{b[i]=0;c[i]=0;}
p=0;
if(flag==0)
{
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
{
if(a[i][j]==1)
{
cout<<"All oranges cannot be rotten";
getch();
exit(0);
}
}
}
cout<<"All oranges can become rotten in "<<count<<" time frames.";
getch();
exit(0);
}
flag=0;
count++;
}
}

Best solution for the problem till now. Kuddos mate.

Could you explain the logic.

a[3][5] is the test case. b and c are the single dimension arrays that will store x and y coordinate of the given dd matrix that have value as 2.In first for loop inside the while loop, we will find all the coordinates having value as 2 and store the x and y coordinate in b and c array respectively. Next, second for loop inside while loop will make each adjacent value from 1 to 2 for each coordinate having value 2. If all adjacent value are already 2 then flag value will not change and will remain zero else it will become 1 and while loop continues. If flag value become become zero then it will enter inside if statement and check whether array a[3][5] has 1 as a value or not. If yes, then print "All oranges cannot be rotten". else print "All oranges become rotten in count no. of frames". count will increment every time while loop execute.

import java.util.List;
class IntegerPair{
int first;
int second;
public IntegerPair() {
}
public IntegerPair(int f,int s) {
this.first = f;
this.second = s;
}
@Override
public boolean equals(Object obj) {
if(obj instanceof IntegerPair){
IntegerPair pair  = (IntegerPair)obj;
return (this.first == pair.first && this.second==pair.second);
}
return false;
}
@Override
public int hashCode() {
return (first+second);
}
@Override
public String toString() {
// TODO Auto-generated method stub
return ("("+first+","+second+")");
}
}

public class OrangeRotteningBFS {
void solve(int arr[][]){
if(arr!=null && arr[0]!=null){
int res = 0;
int m = arr.length;
int n = arr[0].length;
/**
* Adding all the 2's in the matrix in queue i.e. rooten oranges coordinates
*/
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(arr[i][j]==2){
}
}
}
/**
* considering rooten orange can rot only four of its neighbour's
* right , left , up , down
*/
int dx[] = {0,-1,0,1};
int dy[] = {-1,0,1,0};
while(!queue.isEmpty()){
int sz = queue.size();
boolean flag = true;
while(sz>0){
IntegerPair p = queue.get(0);
queue.remove(0);
for(int i=0;i<4;i++){
int _x = p.first + dx[i];
int _y = p.second + dy[i];
// checking the boundary condition
if(_x>=0 && _x<m && _y>=0 && _y<n){
/**
* checking if the neighbour is 1 if so add the co-ordinate to queue
* and set it value as 2
*/
if(arr[_x][_y]==1){
flag = true;
arr[_x][_y] = 2;
}
}
}
sz--;
}
if(flag){
res++;
}
}
System.out.println("Time " + res);
int unRottenOranges = 0;
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(arr[i][j]==1){
unRottenOranges++;
}
}
}
System.out.println("Unrotten Oranges"+unRottenOranges);
System.out.println((unRottenOranges==0)? res:-1);
}else{
System.out.println("Input is null");
}
}
}

public class Microsoft10_rottenOranges {
public static void main(String[] args) {
int mat[][] = { { 2, 1, 0, 2, 1 }, { 1, 0, 1, 2, 1 }, { 1, 0, 0, 2, 1 } };
System.out.println(days(mat));
}

static int days(int mat[][]) {
int m = mat.length;
int n = mat[0].length;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
int val = mat[i][j];
if (val == 2) {
}
}
}

q.add(new Item(-1, -1, -1)); // end of time-slot 1
int dayCount = 0;

//to reach neighbours
int X[] = { -1, 1, 0, 0 };
int Y[] = { 0, 0, -1, 1 };

boolean rottedInThisRound = false;

// apply BFS
while (!q.isEmpty()) {
Item curItem = q.poll();
if (curItem.val == -1) {
if (!rottedInThisRound) {
break;
}
dayCount++;
rottedInThisRound = false;
continue;
}
// make all it's neighbors .. rotten
int row = curItem.row;
int col = curItem.col;
for (int i = 0; i < 4; i++) {
if (isValid(row + X[i], col + Y[i], mat)) {
mat[row + X[i]][col + Y[i]] = 2;
rottedInThisRound = true;
q.add(new Item(row + X[i], col + Y[i], 2));
}
}
}

// check if any orange is not rotten (==1)
if (!checkAllRotten(mat)) {
return -1;
}
return dayCount;
}

static boolean checkAllRotten(int mat[][]) {
for (int i = 0; i < mat.length; i++) {
for (int j = 0; j < mat[0].length; j++) {
if (mat[i][j] == 1) {// if any of them is not rotten
return false;
}
}
}
return true;
}

static boolean isValid(int i, int j, int mat[][]) {
int m = mat.length;
int n = mat[0].length;
return i < m && j < n && i >= 0 && j >= 0 && mat[i][j] == 1;
}

private static class Item {
int row;
int col;
int val;

public Item(int i, int j, int val) {
this.row = i;
this.col = j;
this.val = val;
}

@Override
public String toString() {
return "[" + row + "][" + col + "]:" + val;
}
}
}