Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
Input:
I have some arrays, like:
1, 2, 3, 4, 5
2, 1, 3, 4, 5
3, 2, 5, 4, 1
5, 4, 3, 1, 2
.....
All of them are non repeating permutations of 5 digits - 5C5. Rows can repeat, but any digit in row is unique.
Aim:
Count how many arrays of each type (permutation) are in input data.
My thoughts:
5C5 says that there's only 120 unique rows can be. So I can store counters in int[120] array. And increment them while reading input.
My question:
Is there any efficient algorithm to convert (hash) this array into array index?
Preferable language is C, with it's pointers and manual memory management. In perfect, I'm trying to do something like:
FILE *f;
int counters[120] = {0};
char seq[20];
parse_line(f, seq); #scans and parses string into array
counters[hash(seq)]++;
PS:
I was inspired for this question by solving "UVa 157 - Recycling". Later I saw solutions and understood that I misunderstood task, but question left unanswered.
Do a base conversion. The first digit is in base 5, the second in base 4, then base 3, and base 2. So, for example:
1, 2, 3, 4, 5 -> 0 * 4*3*2*1 + 0 * 3*2*1 + 0 * 2*1 + 0 * 1 -> 0
2, 1, 3, 4, 5 -> 1 * 4*3*2*1 + 0 * 3*2*1 + 0 * 2*1 + 0 * 1 -> 24
3, 2, 5, 4, 1 -> 2 * 4*3*2*1 + 1 * 3*2*1 + 2 * 2*1 + 1 * 1 -> 59
5, 4, 3, 1, 2 -> 4 * 4*3*2*1 + 3 * 3*2*1 + 2 * 2*1 + 0 * 1 -> 118
5, 4, 3, 2, 1 -> 4 * 4*3*2*1 + 3 * 3*2*1 + 2 * 2*1 + 1 * 1 -> 119
Remember to only count numbers you haven't seen when choosing the digit! Walking carefully through the third row of the above:
3, 2, 5, 4, 1
At first, we have the following mapping of numbers to digits:
1 2 3 4 5
0 1 2 3 4
Since the first number is 3, the first digit is 2. Now we delete 3 from the numbers, giving
1 2 4 5
0 1 2 3
The next number is 2, so the next digit is 1. The mapping is now
1 4 5
0 1 2
The next number is 5, so the next digit is 2. The mapping is now
1 4
0 1
The next number is 4, so the next digit is 1. The last digit will be 0 though it won't contribute anything to the sum -- the last digit is in unary, so it will always be 0. So the numbers 32541 correspond to the digits 21210.
To calculate the value of this number in base 10, we use the usual base conversion routine: we multiply the "column value" by the current column's base, then add in the value of the current digit times the column value. So:
0 * 1
+ 1 * (1*1)
+ 2 * (2*1*1)
+ 1 * (3*2*1*1)
+ 2 * (4*3*2*1*1)
-----------------
59
See also the wikipedia page on factorial number systems.
Simplest but memory consuming solution is to create non-colliding hash. Convert the array to number, assuming that permutations contains only 5 digits. The max value of number can only be 54321. Take A[54321], calculate number from the digits and increment counter.
Theoritically the optimum collision free hash has following expression:
If S = s0s1s2...sn-1
Hash(S) = s0*M0 + s1*M1 + s2*M3... sn-1*Mn-1
where M is size of set of digits si can take.
In your case, M is 5 and n is 5,
So max value of hash needs to be
1*50 + 2*51 + 3*52 + 4*53 + 5*54 = 3711.
Related
I know that this is apparently a simple question. But I can't get a better approach to get better efficiency. Here's what I'm trying. It is very naive but I still can't get it correct.
Sort the array. (Divide and Conquer)
a) Select one element at a time
b) loop through all the remaining elements of the array (in a pair) to get
the difference between them to match the selected element.
Repeat step 2 till at least all the elements are found.
Store all the elements that match the condition.
Print the stored elements.
Condition A[i] - A[j] = A[k] is equal to A[i] = A[j] + A[k], so we can look for sum.
Sort the array.
For every element search if it is sum of two others using two pointers approach (increment lower index when sum is too small, decrement upper index when sum is too big)
Resulting complexity is quadratic
Just out of interest, we can solve this problem in O(n log n + m log m) time, where m is the range, using a Fast Fourier Transform.
First sort the input. Now consider that each of the attainable distances between numbers can be achieved by subtracting one difference-prefix-sum from another. For example:
input: 1 3 7
diff-prefix-sums: 2 6
difference between 7 and 3 is 6 - 2
Now let's add the total (the rightmost prefix sum) to each side of the equation:
ps[r] - ps[l] = D
ps[r] + (T - ps[l]) = D + T
Let's list the differences:
1 3 7
2 4
and the prefix sums:
p => 0 2 6
T - p => 6 4 0 // 6-0, 6-2, 6-6
We need to efficiently determine the counts of all the different achievable differences. This is akin to multiplying the polynomial with coefficients [1, 0, 0, 0, 1, 0, 1] by the polynomial with coefficients, [1, 0, 1, 0, 0, 0, 0] (we don't need the zero coefficient in the second set since it only generates degrees less than or equal to T), which we can accomplish in m log m time, where m is the degree, with a Fast Fourier Transform.
The resultant coefficients would be:
1 0 0 0 1 0 1
*
1 0 1 0 0 0 0
=>
x^6 + x^2 + 1
*
x^6 + x^4
= x^12 + x^10 + x^8 + 2x^6 + x^4
=> 1 0 1 0 1 0 1 0 1 0 0 0 0
We discard counts of degrees lower than or equal to T, and display our ordered results:
1 * 12 = 1 * (T + 6) => 1 diffs of 6
1 * 10 = 1 * (T + 4) => 1 diffs of 4
1 * 8 = 1 * (T + 2) => 1 diffs of 2
If any of the coefficients, their negatives, or T are in our set of array elements, we have a match.
inputArray=[5, 1, 2, 3, 1, 4]
product = -1000
f = 0
for f in range(len(inputArray)):
try:
if product< inputArray[f] * inputArray[f+1]:
product = inputArray[f] * inputArray[f+1]
print product
except:
'no more'
print product
Result: 5,6
why doesn't it keep multiply the rest of the adjacent elements?
If you'd like that as an official answer, the explanation is below:
It does multiply on every iteration. It just doesn't print and redefine product unless product is less than the value of this iteration multiplied by next iteration. so visualize it like so:
-1000 < 5 so print. now the value of product is 5.
5 > 1 * 2 so do nothing.
5 < 2 * 3 so print. the value of product is now 6.
6 > 3 * 1 so do nothing.
6 > 1 * 4 so do nothing.
So you would have printed only 5 and 6.
The question is - to find the sum of all maximum values from all subarrays. For instance, I have the array {2, 8, 4, 3, 5}, the solution will be 92. Where all of my subarrays are:
{2},{8},{4},{3},{5},
{2,8},{8,4},{4,3},{3,5},
{2,8,4},{8,4,3},{4,3,5},
{2,8,4,3},{8,4,3,5},
{2,8,4,3,5}
And all maximum values from all subarrays are:
2 - 8 - 4 - 3 - 5 -
8 - 8 - 4 - 5 -
8 - 8 - 5 -
8 - 8 -
8
Do you know the way to solve this problem in linear time complexity?
It should be very straightforward. See the following algorithm
sum = 0
max = 0
for every array 'arr' in the array of arrays
do
for every element 'arri' in the array 'arr'
do
if arri >= max, max = arri
end for
max = 0
sum = sum + max
end for
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
Given an array[] of positive integers and another integer k, I have to find number of subset whose sum is multiple of k(sum is evenly divisible by k).
For example,
array[] = {1, 2, 3, 4}, k = 3
Subset sums are,
1 = 1
1 + 2 = 3
1 + 2 + 3 = 6
1 + 2 + 3 + 4 = 10
2 = 2
2 + 3 = 5
2 + 3 + 4 = 9
3 = 3
3 + 4 = 7
4 = 4
Thus, {3, 6, 9} are multiple of k = 3 and the answer is 3. For the same array above and k = 2, answer will be 4 = {6, 10, 2, 4}
How to implement it efficiently for array size 1 million.
This is a close variant of Subset Sum Problem, and as the original, it is NP-Complete (Reduction from Partition Problem is trivial).
It can be solved using Dynamic Programming by following the recursive formulas:
D(0,0) = true
D(0,x) = false x > 0
D(i,x) = false x < 0
D(i,x) = D(i-1,x) OR D(i-1,x-arr[i])
In here, D(i,x) is true if and only if you can use a subset of the first i elements to build the number x.
This can be calculated efficiently using Dynamic Programming.
When you are done, simply count the number of values of i such that D(n,k*i) = true
This will take O(n*W) time where n is the number of elements, and W is the sum of them.
This seems like a clear use of using recursion.
for each value in array
test value by itself
test all combinations of remaining array, both with value added and without value added.
I suppose the title might be a little misleading, but I couldn't think of a better one.
I have an array A[], all but one of whose elements occurs some number of times that is a multiple of 15, e.g. 2 occurs 30 times, 3 occurs 45 times. But one element occurs x times where x is not a multiple of 15. How do I print the number x. I'm looking for a linear solution without a hash-table.
Thanks.
There was similar question here, on StackOverflow, but i can't find it.
Lets use 3 instead of 15, because it will be easier and i think that it is completely equivalent. The sequence will be 4, 5, 4, 5, 3, 3, 4, 5, in binary 100, 101, 100, 101, 11, 11, 100, 101.
You can do the following: sum all values in least significant bit of numbers and take remainder over 3 (15 originally):
bit1 = (0 + 1 + 0 + 1 + 1 + 1 + 0 + 1) % 3 = 5 % 3 = 2 != 0
if it is != 0 then that bit is equal to 1 in number that we are trying to find. Now lets move to the next:
bit2 = (0 + 0 + 0 + 0 + 1 + 1 + 0 + 0) % 3 = 2 % 3 = 2 != 0
bit3 = (1 + 1 + 1 + 1 + 0 + 0 + 1 + 1) % 3 = 6 % 3 = 0 == 0
So we have bit3 == 0, bit2 != 0, bit1 != 0, making 011. Convert to decimal: 3.
The space complexity is O(1) and time complexity is O(n * BIT_LENGTH_OF_VARS), where BIT_LENGTH_OF_VARS == 8 for byte, BIT_LENGTH_OF_VARS == 32 for int, etc. So it can be large, but constants don't affect asymptotic behavior and O(n * BIT_LENGTH_OF_VARS) is really O(n).
That's it!