I am a new graduated student and I got an interview from a big company. During the interview,I met this question :
"How to check whether there is a path for a string in a matrix of characters? It moves to left, right, up and down in a matrix, and a cell for a movement. The path can start from any entry in a matrix. If a cell is occupied by a character of a string on the path, it cannot be occupied by another character again."
For example, the matrix below with three rows and four columns has a path for the string “BCCED” . It does not have a path for the string “ABCB”, because the first “B” in the string occupies the “B” cell in the matrix, and the second “B” in the string cannot enter into the same cell again.
A B C E
S F C S
A D E E
I used a crappy way to solve this question because I had no ideas how to solve matrix like this in Objective-C.
I have already found a lot of similar questions on other websites,mostly using java not OC...
Can someone show me some good ways in Objective-C to solve this question?
Thank you very much.
This is the classic case to solve with backtracking, The usual scenario is that you are faced with a number of options, and you must choose one of these. After you make your choice you will get a new set of options; just what set of options you get depends on what choice you made. This procedure is repeated over and over until you reach a final state. There is a nice explanation of backtracking here http://www.cis.upenn.edu/~matuszek/cit596-2012/NewPages/backtracking.html
/*
This part needs to be in the caller program, which will pass the original array and input. I have taken input as an array, you can use input as a string for your question, in the end for the algorithm it doesn't matter.
NSArray* a1 = @[
@[@"A", @"B", @"C", @"E"],
@[@"S", @"F", @"C", @"S"],
@[@"A", @"D", @"E", @"E"],
];
NSArray* input = @[ @"A", @"B", @"C", @"B" ];
BOOL result = [self checkPath:a1 andInput:input];
*/
-(BOOL) checkPath:(NSArray*)a1 andInput:(NSArray*)input
{
// Create a test array to keep track of what options you have already used.
NSMutableArray* testArray =
[[NSMutableArray alloc] init];
[testArray addObject:[[NSMutableArray alloc] init]];
[testArray addObject:[[NSMutableArray alloc] init]];
[testArray addObject:[[NSMutableArray alloc] init]];
// Initialize all the elements of the test array to zero, You should replace zero with 1 when you match the element at a certain index.
for(int i = 0; i < 3; i++) {
for (int j = 0; j< 4; j++) {
testArray[i][j] = @0;
}
}
for(int i = 0; i < 3; i++) {
for (int j = 0; j< 4; j++) {
NSLog(@"%@", a1[i][j]);
}
}
BOOL res = NO;
int i = 0, j = 0;
while (!res && i <3) {
while (!res && j <4) {
if( [input[0] isEqualToString:a1[i][j]])
{
testArray[i][j] = @1;
res = [self doesPathExist:input dictionaryArray:a1 startIndexX:i andStartIndexY:j compareIndex:1 andMarkerTable:testArray];
// Reset the test option incase the chosen option wasn't success
testArray[i][j] = [NSNumber numberWithBool:res];
}
j++;
}
i++;
}
return res;
}
/**
* Check if the path exist in array a1 starting at index x and y for elements of array input, starting at element c
*
* @param input input array for which you want to check path in a1
* @param a1 array in which we want to check the path
* @param x row number to start with
* @param y column number to start with
* @param c index of elemnet to check in input array
* @param markerTable table that decides which elements have already been used.
*
* @return yes if path exist for array input in a1 otherwise No
*/
-(BOOL)doesPathExist:(NSArray*)input dictionaryArray:(NSArray*)a1 startIndexX:(int) x andStartIndexY:(int) y compareIndex:(int)c andMarkerTable:(NSMutableArray*) markerTable
{
NSUInteger n = markerTable.count;
NSUInteger m = ((NSArray*)markerTable[0]).count;
NSUInteger N = input.count;
if (c == N)
{
NSLog(@"YES, Path Exists");
return YES;
}
else
{
BOOL result = NO;
while (c < N) {
int left = y -1;
int right = y + 1;
int top = x - 1;
int bottom = x + 1;
if (left>=0 && ![markerTable[x][left] isEqualToNumber: @1]) {
if( [a1[x][left] isEqualToString:input[c]]){
// set marker table value as 1 to mark the match
markerTable[x][left] = @1;
result = [self doesPathExist:input dictionaryArray:a1 startIndexX:x andStartIndexY:left compareIndex:c+1 andMarkerTable:markerTable];
// reset the marker table based on result, we do a reset of marker
// table at the index to make sure if this combination fails and there
// is another combination involving this element it should be able to use this element.
markerTable[x][left] = [NSNumber numberWithBool:result];
return result;
}
}
if (right<m && ![markerTable[x][right] isEqualToNumber:@1]) {
if([a1[x][right] isEqualToString:input[c]]) {
markerTable[x][right] = @1;
result = [self doesPathExist:input dictionaryArray:a1 startIndexX:x andStartIndexY:right compareIndex:c+1 andMarkerTable:markerTable];
markerTable[x][right] = [NSNumber numberWithBool:result];
return result;
}
}
if(top >=0 && ![markerTable[top][y] isEqualToNumber:@1]) {
if([a1[top][y] isEqualToString:input[c]]) {
markerTable[top][y] = @1;
result = [self doesPathExist:input dictionaryArray:a1 startIndexX:top andStartIndexY:y compareIndex:c+1 andMarkerTable:markerTable];
markerTable[top][y] = [NSNumber numberWithBool:result];
return result;
}
}
if(bottom < n && ![markerTable[bottom][y] isEqualToNumber:@1]) {
if([a1[bottom][y] isEqualToString:input[c]]) {
markerTable[bottom][y] = @1;
result = [self doesPathExist:input dictionaryArray:a1 startIndexX:bottom andStartIndexY:y compareIndex:c+1 andMarkerTable:markerTable];
markerTable[bottom][y] = [NSNumber numberWithBool:result];
return result;
}
}
c++;
}
NSLog(@"Returning false");
return NO;
}
}
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments