This question was asked in interview and deals with recursion/backtracking. Suppose we have two arrays of booleans:bool* source
and bool* target
,each of them the same length n
(source/target/n are given as arguments). The goal of the question is to transform source
to target
using operation switch.
Definition: operation switch(int i, bool* arr)
inverts the value at arr[i] and arr[i-1] and arr[i+1] (if these indices are in the range 0...n-1).
In other words, switch
operation will usually flip three bits (i and its neighbors), but only two at the ends.
For example:
Thank you in advance for the suggestions about the algorithm.
Difference between Recursion and Backtracking: In recursion, the function calls itself until it reaches a base case. In backtracking, we use recursion to explore all the possibilities until we get the best result for the problem.
To ace your coding interview for a software engineering job, you'll need to understand backtracking. Backtracking is a technique that solves a problem by exploring possible solutions to its sub-problems, abandoning any that will not lead to a valid solution.
Backtracking uses recursion to solve it's problems. It does so by exploring all the possiblities of any problem, unless it finds the best and feasible solution to it. Recursion occurs when a function calls itself repeatedly to split a problem into smaller sub-problems, until it reaches the base case.
Recursion is the first step of the FAST Method. Suffice to say, it is absolutely essential that you be prepared to solve recursion interview questions in your interview. It is almost guaranteed that you will see at least one or two recursive problems at any given onsite interview.
Using backtracking you can have O(n) solution. Why?
Starting at left an moving right and backtracking is best approach.
At any time time you have to go back at most by two steps. For instance if you are at index n, you can change only index n-1, but not index n-2 and once Or more precisely when you reach index n+2 you only have to check index n.
You can have at worst 2 solutions.
Solution (in python)
def light(arr,n):
for i in range(max([0,n-1]),min([len(arr),n+2])):
arr[i] = not arr[i]
return arr
goal = [True]*500
def trackback(arr,index,moves):
if index == len(arr):
if arr == goal:
print(moves)
return
if index > 1:
if arr[index-2] != goal[index-2]:
return
#print(arr,index,moves)
#do not make switch
trackback(arr,index+1,moves)
#make switch
moves=moves+[index]
arr=light(arr,index)
trackback(arr,index+1,moves)
arr=light(arr,index) #undo move
arr=[False]*500
trackback(arr,0,[])
output
[1, 4, 7, 10, 13, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46, 49, 52, 55, 58, 61, 64, 67, 70, 73, 76, 79, 82, 85, 88, 91, 94, 97, 100, 103, 106, 109, 112, 115, 118, 121, 124, 127, 130, 133, 136, 139, 142, 145, 148, 151, 154, 157, 160, 163, 166, 169, 172, 175, 178, 181, 184, 187, 190, 193, 196, 199, 202, 205, 208, 211, 214, 217, 220, 223, 226, 229, 232, 235, 238, 241, 244, 247, 250, 253, 256, 259, 262, 265, 268, 271, 274, 277, 280, 283, 286, 289, 292, 295, 298, 301, 304, 307, 310, 313, 316, 319, 322, 325, 328, 331, 334, 337, 340, 343, 346, 349, 352, 355, 358, 361, 364, 367, 370, 373, 376, 379, 382, 385, 388, 391, 394, 397, 400, 403, 406, 409, 412, 415, 418, 421, 424, 427, 430, 433, 436, 439, 442, 445, 448, 451, 454, 457, 460, 463, 466, 469, 472, 475, 478, 481, 484, 487, 490, 493, 496, 499]
[0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, 60, 63, 66, 69, 72, 75, 78, 81, 84, 87, 90, 93, 96, 99, 102, 105, 108, 111, 114, 117, 120, 123, 126, 129, 132, 135, 138, 141, 144, 147, 150, 153, 156, 159, 162, 165, 168, 171, 174, 177, 180, 183, 186, 189, 192, 195, 198, 201, 204, 207, 210, 213, 216, 219, 222, 225, 228, 231, 234, 237, 240, 243, 246, 249, 252, 255, 258, 261, 264, 267, 270, 273, 276, 279, 282, 285, 288, 291, 294, 297, 300, 303, 306, 309, 312, 315, 318, 321, 324, 327, 330, 333, 336, 339, 342, 345, 348, 351, 354, 357, 360, 363, 366, 369, 372, 375, 378, 381, 384, 387, 390, 393, 396, 399, 402, 405, 408, 411, 414, 417, 420, 423, 426, 429, 432, 435, 438, 441, 444, 447, 450, 453, 456, 459, 462, 465, 468, 471, 474, 477, 480, 483, 486, 489, 492, 495, 498]
You can see that simplest solution would be just running two for loops. First solution set first light/switch and second does not. All remaining switching are then decided
#do not switch first light
for i in range(1,len(goal)+1):
if goal[n-1] != arr[n-1]:
light(arr,n)
check_solution()
#switch first light
switch(arr,n)
for i in range(1,len(goal)+1):
if goal[n-1] != arr[n-1]:
light(arr,n)
check_solution()
As far as I understand the problem, the main observation is that we never need to perform more than one switch on any position. This is because switching twice is the same as not switching at all, so all even switches are equivalent to 0 switches and all odd switches are as good as 1 switch.
Another thing is that the order of the switches don't matter. switching the i-th and i+1-th elements is the same as switching i+1-th and then the i-th. The pattern obtained at the end is the same.
Using these two observations, we can simply try out all possible ways of applying switch to the n length array. This can be done recursively (i.e. doing a switch at index i/not doing a switch at index i and then trying out i+1) or by enumerating all 2**n n bit bitmask and using them to apply switches until one of them creates the target value.
Below is my hack at the solution. I have packed the arrays into ints and used them as bitmasks to simplify the operations. This prints out the indices that need to be switched to get the target array and prints "Impossible" if the target is not obtainable.
#include <cstdio>
int flip(int mask, int bit){
return mask^(1<<bit);
}
int switch_(int mask, int index, int n){
for(int i=-1;i<=+1;i++){
if ((index+i)>=0 && (index+i)<n) mask=flip(mask,index+i);
}
return mask;
}
int apply(int source, int flips, int n){
int result=source;
for(int i=0;i<n;i++){
if (flips&(1<<i)) result=switch_(result,i,n);
}
return result;
}
void solve(int source, int target, int n){
bool found=false;
int current=0;
int flips=0;
for(flips=0;flips<(1<<n) && !found;flips++){
current=apply(source,flips,n);
found=(current==target);
}
if (found){
flips--;
for(int i=0;i<n;i++){
if (flips&(1<<i)) printf("%d ",n-i-1); //prints the indices in descending order
}
printf("\n");
}
else{
printf("Impossible\n");
}
}
int array2int(int* arr, int n){
int ret=0;
for(int i=0;i<n;i++){
ret<<=1;
if (arr[i]==1) ret++;
}
return ret;
}
int main(){
int source[]={0,0,0,0};
int target[]={1,1,1,1};
int n=4;
solve(array2int(source,n),array2int(target,n),n);
return 0;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With