My data structure is a path represented by a list of cities. If, for example, the cities are
A, B, C, D
A possible configuration could be: A, B, D, C or D, C, A, B.
I need two compare two paths in order to find the differences between these two, in such a way that the output of this procedure returns the set of swapping operations necessary to transform the second path into the first one.
For example, given the following paths:
X = {A, B, D, C}
Y = {D, C, A, B}
indexes = {0, 1, 2, 3}
A possible way to transform the path Y into X would be the set of the following swaps: {0-2, 1-3}.
{D, C, A, B} --> [0-2] --> {A, C, D, B} --> [1-3] --> {A, B, D, C}
Is there any known (and fast) algorithm that allows to compute this set?
Your problem looks like a problem of counting the minimal number of swaps to transform one permutation to another.
In fact it's a well known problem. The key idea is to create new permutation P such that P[i] is the index of X[i] city in the Y. Then you just calculate the total number of cycles C in the P. The answer is the len(X) - C, where len(X) is the size of X.
In your case P looks like: 3, 4, 1, 2. It has two cycles: 3, 1 and 4, 2. So the answer is 4 - 2 = 2.
Total complexity is linear.
For more details see this answer. It explains this algorithm in more details.
EDIT
Okay, but how we can get swaps, and not only their number? Note, that in this solution we reorder each cycle independently doing N - 1 swaps if the length of cycle is N. So, if you have cycle v(0), v(1), ..., v(N - 1), v(N) you just need to swap v(N), v(N - 1), v(N - 1), v(N - 2), ..., v(1), v(0). So you swap cycle elements in reverse order.
Also, if you have C cycles with lengths L(1), L(2), ..., L(C) the number of swaps is L(1) - 1 + L(2) - 1 + ... + L(C) - 1 = L(1) + L(2) + ... + L(C) - C = LEN - C where LEN is the length of permutation.
Related
I had an interview and I was not able to give a best approach for the problem.
A=1, B=0
- Operation L: A=2A-B
- Operation R: B=2B-A
For each step, only one operation(L or R) is taken place.
For a given number N, what is the minimum number of operations required to make A or B equals to N?
The most important one is an efficiency.
Thanks in advance.
In k operations you can get all values of N in [-(2^k)+1, 2^k].
Notice that abs(A) + abs(B) = 2^k for all possible k paths, and that A & B exactly cover the range [-(2^k)+1, 2^k] in the set of paths of length k.
k=0: (1,0)
k=1: (1,-1), (2,0)
k=2: (1,-3), (2,-2), (3,-1), (4,0)
etc...
Given N we can find the minimum k via log. Then we know the final pair is (N, N - 2^k) (or (N-2^k, N) if N <= 0). It's easy to follow the path back up to k=0 because one of the two elements will be out of range for the next smaller k.
E.g., N = 35.
Log2(35) = 5.13, so we use k=6.
2^6 = 64, so our final pair is (35, -29)
(35,-29) -> (3,-29) -> (3, -13) -> (3, -5) -> (3,-1) -> (1,-1) -> (1,0)
Figuring out k is O(1), finding the path is O(k) which is O(log(abs(N)).
It's not likely you need to prove anything in an interview, but if you did, you could use this:
By observation: A - B = 2^k for k steps observed for small k.
Then via induction: we have some valid (A, B) s.t. A-B = 2^k. Then L gets us (2A-B, B), but 2A-B-B = 2A-2B = 2(A-B) = 2^(k+1) as desired. Similarly for R.
It would be a challenging task for an interview but I would start with the recursion of trying to find the origin from the result. Given valid (A', B), where A' is the target we are after,
A' = 2A - B
for some A, which means that
A = (A' + B) / 2
The latter tells us that all (A' + B) in the path must be divisible by 2, and since the path ends (starts) at 1, all the (A' + B) in it are powers of 2.
Another property we can observe, although it may not be relevant to the solution is that once we switch in the first step to (even, even) or (odd, odd), we cannot switch back.
The problem statement:
Given a list of pairs {A|B}
Find the minimum sum where you must take 'm' values from 'A' and 'n' values from 'B'
you may not use the same 'pair' for both A and B
the size of the list will be between 2 and 500 items
the number of items you take (m & n) can also vary
the numbers in the pair (A & B) are ranged 0-9.
There of course can be multiple pair combinations that give you the correct minimum.
For example, given:
1 - {4,5}
2 - {3,2}
3 - {3,1}
4 - {1,0}
and desiring 2 from A, 1 from B
the correct answer is 5
taking 2A(3), 4A(1) and 3B(1).
Another example is:
1 - {5,4}
2 - {2,1}
3 - {6,6}
4 - {2,1}
5 - {5,5}
and desiring 2 from A, 2 from Bthe correct answer is 12
taking 1A(5), 5A(5), 2B(1), 4B(1).
I have solved this using a brute force approach, but of course as the list grows larger, and m/n increase, the performance suffers greatly.
How can I improve on this brute force approach?
What is this class of problem called?
Believe it or not, this is not homework!
It can be formulated as a minimum-cost flow problem. Let the pairs be (a_i, b_i). Create vertices s, t, a, b, u_i and arcs from s to a (capacity m, cost 0), from s to b (capacity n, cost 0), from a to u_i (capacity 1, cost a_i), from b to u_i (capacity 1, cost b_i), from u_i to t (capacity 1, cost 0). Send m + n units of flow as cheaply as possible from s to t. Flow on a->u_i means that a_i is chosen. Flow on b->u_i means that b_i is chosen.
It also can be solved by dynamic programming. Let Cost[i, j, k] be the minimum sum for choosing i A's and j B's from the first k pairs. Then we have recurrence relations
Cost[0, 0, 0] = 0
Cost[i, j, 0] = infinity
(for all i, j such that i > 0 or j > 0)
Cost[i, j, k] = min {Cost[i, j, k-1],
Cost[i-1, j, k-1] + a_k,
Cost[i, j-1, k-1] + b_k}
(for all i, j, k such that k > 0).
Trace back the minimum arguments to reconstruct the optimal choices.
Given a permutation of natural integers from 1 to N, inclusive. Initially, the permutation is 1, 2, 3, ..., N. We are also given M pairs of integers, where the i-th is (Li,Ri). In a single turn we can choose any of these pairs (let's say with the index j) and arbitrarily shuffle the elements of our permutation on the positions from Lj to Rj, inclusive (the positions are 1-based). We are not limited in the number of turns and you can pick any pair more than once.
The goal is to obtain the permutation P, that is given. If it's possible, output "Possible", otherwise output "Impossible".
Example : Let N=7 and M=4 and array be [3 1 2 4 5 7 6] and queries are :
1 2
4 4
6 7
2 3
Here answer is Possible.
Treat each pair as an interval, compute the union of intervals as a list of non-overlapping intervals, and then test, for each i, whether the value at position i of the permutation either is i or is in the same non-overlapping interval as i.
This works because, if we have a <= b <= c <= d with pairs (a, c) and (b, d), then by repeatedly invoking (a, c) and (b, d), we can get any permutation that we could get with (a, d). Conversely, (a, d) enables any permutation that we could get with (a, c) and (b, d). Once the list of pairs is non-overlapping, it's clear that we can move element i to position j != i if and only if i and j are in the same interval.
Im looking for an algorithm to reduce a list (playlist) of ordered but not unique items.
Searched for set theory but havent found anything suitable yet
Examples
[a, b, b, c] -> [a, b, b, c] Cannot be reduced.
[a, b, b, a, b, b] -> [a, b, b].
[b, b, b, b, b] -> [b].
[b, b, b, b, a] -> [b, b, b, b, a] Cannot be reduced.
Thinking of getting all existing sublists and count each instance.
If there is such a sublist where the count times the sublist length is equal to the orginal list, take the shortest sublist matching this criteria.
This seems a bit brute force, there must be a simpler/faster solution available.
For starters, you don't need to check all sublists -- just those with lengths that are factors of the length of the full list.
If your main concern is coding simplicity rather than raw speed, just let a regex engine solve the problem:
/^(.+?)\1+$/
Which is a variant on Abigail's awesome Perl regex to find prime numbers.
For each n <= N (where N is the length of the list), if n is a factor of N. If it is, then check if repeating the sublist of the first n characters generates the original list. If it does, then you've found a potential answer (the answer is the shortest). This should get you down to less than O(N^2) but still the same order of efficiency as brute force in the worst case.
You can do some pruning by noting that, if for example a sublist of length 2 successfully generates the first 4 characters but not the full list, then a sublist of length 4 will fail. You can keep a list of all such sublist lengths to not check and this will cut down on some computation.
Encode every set element with a prime number.
Ex:
a -> 2
b -> 3
c -> 5
etc.
Now, you need two more lists to maintain.
First list is for primes, second is for their exponents.
The idea is; when you stumble upon an element, record it's prime number and how many times in succession it appears.
For [a, b, b, c], you get this:
[2, 3, 3, 5]
Which can be recorded as:
[2, 3^2, 5]
or, more precisely:
[2^1, 3^2, 5^1]
and you maintain two lists:
[2,3,5] // primes in succession - list [p]
[1,2,1] // exponents - list [e]
Now, you iterate through these two lists from ends to middle, by checking if first element [p]^[e] is the same as last element; if it is, then second with next to last and so on... If all of them are the same, your list can be reduced.
In this example, you check if 2^1*5^1 == 3^2*3^2; and since it's not, it cannot be reduced.
Let's try [a, b, b, a, b, b]:
This is encoded as
[2^1, 3^2, 2^1, 3^2]
or,
[2, 3, 2, 3] // primes
[1, 2, 1, 2] // exponents
Now, we check if 2^1 * 3^2 == 3^2 * 2^1 (first prime, first exponent multiplied with last prime, last exponent, and then compared with second against next to last)
Since this holds, it is reducible.
Let's try [b, b, b, b, b]:
This can be encoded as
[3^5]
or,
[3] // primes
[5] // exponents
This is a special case: if you've got 1 element lists, then your original list is reducible.
Let's try [b, b, b, b, a]:
This can be encoded as
[3^4, 2^1]
or,
[3, 2] // primes
[4, 1] // exponents
We check if 3^4 == 2^1, and since it is not, your list is not reducible.
Let's try [a, b, a, b, a, b]:
This can be encoded as
[2^1, 3^1, 2^1, 3^1, 2^1, 3^1]
or,
[2, 3, 2, 3, 2, 3]
[1, 1, 1, 1, 1, 1]
Trying the above procedure works, because 2^1 * 3^1 == 3^1 * 2^1 == 2^1 * 3^1
So, the algorithm would be something like this:
Encode all numbers to primes.
Iterating through your list, make two lists and populate them as described
Now that you have your two lists, p and e, both of them having length n do this:
var start = p[0]^e[0] * p[n-1]^e[n-1]
var reducible = true;
for (int i = 0; i < n/2, ++i) :
if ( (p[i]^e[i] * p[n-i]^e[n-i]) != start ) :
reducible = false;
break;
Note: I didn't really code this algorithm and try it out for various inputs. It's just an idea.
Also, if a list is reducible, from it's length and length of n, it shouldn't be too hard to see how to reduce the original list to its basic form.
Second note: if anyone sees a mistake above, please correct me. It's possible that nothing of this really works since it's late and my concentration isn't optimal.
Here's some simple code that should run in close to linear time (at worst O(n lg lg n) I think, relying on some higher math).
f(x) {
i = 1;
while (i <= size(x) / 2) {
if (size(x) % i != 0) { i++; continue;}
b = true;
for (j = 0; j + i < x.size(); j++) {
if (x[i] != x[j]) {
b = false;
break;
}
}
if (b) return i;
i = max(i + 1, j / i * i / 2); // skip some values of i if j is large enough
}
return -1;
}
Essentially, the above performs the naive algorithm, but skips some periodicities which are known to be impossible due to earlier "near-misses". For example, if you try a period of 5 and see "aaaabaaaabaaaabaaaabab", you can safely skip 6, 7,..., 10 since we saw 4 cycles of 5 repeat and then a failure.
Ultimately, you end up doing a linear amount of work plus an amount of work that is linear in sigma(n), the sum of the divisors of n, which is bounded by O(n lg lg n).
*Note that proving the correctness of this skipping is pretty subtle, and I may have made a mistake on the details -- comments welcome.
Got this as an homework assignment and not really sure where to start!
Given the set {1,2,3,4}, you can form six combinations of length two from that set, viz:
{1,2},{1,3},{1,4},{2,3},{2,4},{3,4}
If I was to choose one of the combinations, ({1,2} for example), how can I tell how many of the others are not disjoint to it? In this case it is four: {1,3},{1,4},{2,3}{2,4}
Not really sure about how to go about this mathematically, any pointers in the right direction would be much appreciated.
Number of subsets that can be formed from a set of n items taking r items at a time is
total = P(n, r) = n! / (r! * (n - r)!)
Let s be the selected combination. To find the number of subsets that are not disjoint with s, we start by finding the number of subsets that are disjoint with s - those sets that doesn't have any items in s (lets call that number k). Thus k is the number of subsets that can be formed from a set of n - r items, taking r at a time.
k = P(n - r, r) = (n - r)! / (r! * (n - r - r)!)
= (n - r)! / (r! * (n - 2r)!)
Thus, the number of subsets disjoint with the selected set is:
total - k = P(n, r) - P(n - r, r)
Remember that this includes the selected subset s. Subtract one from this to get the number of disjoint sets with s.
Consider the following example:
//Let n = 6 and r = 2
total = P(n, r) = n! / (r! * (n - r)!) = 6! / (2! * 4!) = 15
k = P(n - r, r) = (n - r)! / (r! * (n - 2r)!) = 4! / (2! * 2!) = 6
answer = 15 - 6 = 9;
answer excluding the selected set s = 8
//Super set:
{123456}
//Possible sub sets:
{12,13,14,15,16,23,24,25,26,34,35,36,45,46,56} //15 items
//Let the selected set be {12}, then sets without 1 and 2:
{34,35,36,45,46,56} //6 items
//9 sets (including the selected set) are not disjoint with the selected set
Maybe start by reading some book or articles on combinatorics ..
If you can program, this library will help you.
I would do something like this:
For each item in my combination ( 1 then 2 ) do the following
* For each item in the set (1, 2, 3, then 4) do the following
** if set item is different from both combination item 1 and 2
*** print out combination item and print out set item
Try Combinatorics or better Permutations.
The sets X = {a, b} and Y are disjoint if a and b both do not appear in Y. Therefore, X and Y are not disjoint if a appears in Y or b appears in Y.
To find out how many other sets are not disjoint with {a, b}, consider all the possibilities: In general all the sets with two elements that are not disjoint with {a, b} are of the form {a, x} or {b, x}, for any x in the original set. If the original set had n elements, then there are n possibilities for {a, x} and another n for
{b, x}, for a total of 2*n*.
However, {a, b} is both of the form {a, x} (for x = b) and of the form {b, x} (for x = a), so we are counting it twice. We must count it zero times, because {a, b} is the same set as the one we were starting with. So we subtract 2, for a total of 2*n* - 2.
But we're still counting {a, a} (for x = a) and {b, b} (for x = b). But those only contain one element each ({a, a} = {a} and {b, b} = {b}), so we shouldn't count them. Therefore we subtract 2, for a total of 2*n* - 4.
For your example, {1, 2, 3, 4} gives n = 4, so the number of elements not disjoint with {1, 2} is 2*4 - 4 = 4.