This task was actually given to us as homework, but the requirement in the homework assignment was to write a recursive method that can return true or false if array A can match array B after we perform a few steps on array A, I’ve already answered this question in a recursive manner, and i am interested in finding if there is a more intelligent approach to it, a certain pattern or equation that can be used to address this type of assignment,
that being said, i am not sure if the homework tag is still relevant, but i added it just in case.
Here are the details:
Given two boolean arrays, identical in length. return true if a given array “init” can match target array “target”,
The catch is: whenever we “flip” the value of one index from true to false and vice-versa, the values in the indexes to the right and left of the current index, flip their value as well (if such an index is within the array bounds of course), for example:
boolean[] init = {true, false, true, false, true, false};
boolean[] target = {false, true, false, true, false, true};
in this case the answer is true, as we can flip the first spot [0] of init array, resulting in:
boolean[] init = {false, true, false, false, true, false);
boolean[] target = {false, true, false, true, false, true};
and then flip the 4th spot [3] in init array, resulting in a match between the init and target arrays:
boolean[] init = {false, true, false, true, false, true};
boolean[] target = {false, true, false, true, false, true};
recursively it was just testing the two options of a “flipped state” or without a “flipped state” and advancing in the array’s index for each test, which will recursively check all the options, eventually returning true if a match is found.
Now focusing back on my question, is there a better approach to this kind of problem without having to check so many options? it doesn’t have to be recursive… as a matter of fact, it may be best if it wasn’t 🙂
so please feel free to share your ideas and suggestions.
Thanks!
How to speed up the implementation (of answering yes/no to the question whether we can transform the array with the given rule):
Represent everything as bits instead of array of true and false value. Then the bit flipping patterns are: 1100…00, 1110…00, 0111…00, …, 0000…11. We will search all the possible ways that the bit flipping pattern can transform an array by doing a BFS (or DFS).
Store whether a transformation is possible with bit set (if the language allows such low level implementation or provided with such library) or array of char/boolean. This will reduce the space used by the transformation. The size of the array/bit set is 2 ^ n.
When you have obtained all the possible transformation, you can answer the question with a fixed number of elements in O(1) by XORing the input and the target, then check whether such transformation exists. Well, if the number of elements varies, then there is not much advantage.
It should be able go up to 20-23 bits while still keep the time under 1-3 seconds (assuming C++ code). For Java, it is probably a tad bit slower, but should be under 30 seconds.
The time complexity is no better than your current method, though.
You can also search for the transformation pattern 0000…01 (terminate early, instead of searching for the whole space of possible transformation), then use the method that Darcy Rayner suggested. The worst case complexity is no better than your current method.
I don’t know if there is any mathematical solution to this problem. Currently, this is all brute force.EDIT
Mathematically, it is possible to prove that we can greedily reduce the difference to at most 1 with the method that Darcy Rayner suggested (by analyzing at the last 2 bits).
It also can be proven that we can negate the whole pattern any time, i.e. for length 3k, trivial, for length 3k + 1, flip at the both ends, and all groups of 3 in the middle, for length 3k + 2, flip at one end, and all groups of 3 in the middle.
So if we have the last bit = 1, we can flip the whole pattern. If the original length is 3k + 1, we end up with 3k differences (true), which can be flipped trivially. If the original length is 3k, we end up with 3k – 1 differences, which we can flip at one end, and flip every group of 3. In those 2 cases (length 3k + 1 and length 3k), transformation is always possible.
I currently has no disproof for the case 3k + 2.