I have a Java computational problem in which I am given an array of integers:
For example:
3 -2 -10 0 1
and I am supposed to compute what is the minimal integer and maximum triplet that
can be formed from these integers. (In this case, min=-30,max=60)
I initially thought that the maximum would always be positive and minimum would always be
negative.
Hence,
My initial algorithm was:
Scan the array and take out the 3 largest elements inside, store into an array.
At the same time, take out the 3 smallest elements inside, store into another array.
By inequalities, we can deduce the following:
+ve = (-)(-)(+) or (+)(+)(+)
-ve = (+)(+)(-) or (-)(-)(-)
Hence, I used the elements from the two arrays that I computed to try to obtain the maximal and minimal triplet. (i.e. In order to obtain the maximal triplet, I compared the triplet formed by the largest 3 with the triplet formed by the smallest 2 and the largest integer)
However, I realized that if all the given integers were negative, my algorithm would be defeated because of the fact that the maximal would be negative. (Vice-versa for minimal)
I know that I can simply add more checks to solve this problem or simply just use the brute force O(N^3) solution. But there must be a better way to solve this problem.
This problem must be solved by recursion and only in O(N) time.
I am in a fix. Could someone please guide me?
Thanks.
There is a O(n) solution if you find the 3 maximum and 2 minimum values in linear times.
But you can also use nlog(n) sorting (i.e. quick sort) to do that job easily.
Then here the solution to find the maximum product triplet in C with explanations in comments -
int cmpfunc (const void * a, const void * b)
{
return ( *(int*)a - *(int*)b );
}
int solution(int A[], int N) {
long product = A[0] * A[1] * A[2];
if (N == 3) {
return product;
}
// Nlog(N)
qsort(A, N, sizeof(int), cmpfunc);
if (A[N - 3] >= 0) {
// if there is at least 3 non-negative value
// then take three maximum values
product = A[N - 1] * A[N - 2] * A[N - 3];
if (A[1] < 0) {
// if there is at least 2 negative value
if (product < A[N - 1] * A[0] * A[1]) {
// then take maximum positive and two minimum negative, if that is more than 3 positive values
product = A[N - 1] * A[0] * A[1];
}
}
} else if (A[N - 1] >= 0) {
// else if there is least 1 non-negative value
// then take maximum positive and two minimum negative
product = A[N - 1] * A[0] * A[1];
} else {
// otherwise, take 3 maximum negative values
product = A[N - 1] * A[N - 2] * A[N - 3];
}
return product;
}
First, you only have to solve one of the two problems, say find the biggest triple product. With this you can find the least by negating all the input values, finding the biggest triple product, and negating to find the answer.
So let's focus on finding the biggest. You have it pretty well worked out. Take the maximum positive number first (if there is one). Then pick either the pair of the two biggest remaining positive numbers or the two biggest (in magnitude) negative numbers, whichever pair has the largest product.
If there are no positive numbers at all, then pick the three smallest negative numbers.
Certainly this can all be done in O(n) time, but this is not an algorithm where recursion has a natural place. You'd have to use trivial tail recursion to substitute for loops.
Related
I want to count all pythagorean triples (primitive and non-primitive) whose hypotenuse is <= N for a given N. This OEIS link gives this count for powers of 10. A simple but somewhat efficient pseudocode can be easily derived from this link or from wikipedia, using the famous Euclid's formula. Interpreted in Java, this can be made into:
public class countPTS {
public static void main(String[] args)
{
long N = 1000000L;
long count = 0;
for (long m = 2 ; m * m + 1 <= N ; m++)
for (long n = 1 + m % 2 ; n < m && n * n + m * m <= N ; n += 2)
if (gcd(m , n) == 1)
count += N / (n * n + m * m);
System.out.println(count);
}
public static long gcd(long a, long b)
{
if (a == 0)
return b;
return gcd(b % a, a);
}
}
Which gives the correct results, but is a bit "slow". Regardless of the actual time complexity of this algorithm in big O notation, it seems to grow like a little bit worse than O(n). It can be easily checked that almost the entire time is spent in gcd calculations.
If C(N) is the count of such triples, then this piece of code written and ran on the latest version of Eclipse IDE, using a modern PC and single threaded, yields C(10^10) = 34465432859 in about 90 seconds. This makes me wonder how the high values in the OEIS link were obtained, the largest being C(10^17).
I suspect that an algorithm with a better time complexity was used, perhaps O(n^2/3) or O(n^3/4), maybe with some more advanced mathematical insight. It is somewhat plausible that the above algorithm was ran but with significant improvements and perhaps multithreaded. Can anyone shed light on this topic and higher values?
TD;LR: There is an approach that is slightly worse than O(N^(2/3)). It consists of enumerating primitive triples with an efficient algorithm up to N^(2/3) and counting the resulting Pythagorean triples, and then using inclusion-exclusion to count Pythagorean primitive triples past that and finding a count of the rest. The rest of this is a detailed explanation of how this all works.
Your direct calculation over primitive triples cannot be made better than O(N). The reason why is that over 60% of pairs of integers are relatively prime. So we can put a lower bound on the number of pairs of relative primes as follows.
There are floor(sqrt(n/2)) choose 2 = O(N) pairs of integers at most sqrt(n/2). The ones that are relatively prime with one even give rise to a primitive Pythagorean triple.
60% of them are relatively prime.
This 60% is contained in the 75% that do not have both numbers even. Therefore when we get rid of pairs with both numbers odd, at least 60% - 25% = 35% of pairs are relatively prime with one of them even.
Therefore there are at least O(n) distinct Pythagorean triples to find whose hypotenuse is less than n.
Given that there are O(N) primitive triples, you'll have to do at least O(N) work to enumerate them. So you don't want to enumerate them all. Instead we'll enumerate up to some point, and then we'll do something else with the rest. But let's make the enumeration more efficient.
Now as you noticed, your GCD checks are taking most of your time. Can we enumerate all of them with hypotenuse less than, say, L more efficiently?
Here is the most efficient approach that I found.
Enumerate the primes up to sqrt(L) with any decent technique. This is O(sqrt(L) log(L) with the Sieve of Eratosthenes, that is good enough.
Using this list, we can produce the set of odd numbers up to sqrt(L), complete with their prime factorizations, fairly efficiently. (Just recursively produce prime factorizations that fit in the range.)
Given an odd number and its prime factorizations, we can run through the even numbers and quickly find which are relatively prime. That gives us the primitive Pythagorean triples.
For step 3, create a PriorityQueue whose elements start off pairs (2*p, 2*p) for each distinct prime factor p. For example for 15 we'd have a queue with (6, 6) and (10, 10). We then do this:
i = the odd number we started with
j = 2
while i*i + j*j < L:
if queue.peek()[0] == i:
while queue.peek()[0] == i:
(x, y) = queue.pop()
queue.add((x+y, y))
else:
i*i + j*j is the hypotenuse of a primitive Pythagorean triple
This is very slightly superlinear. In fact the expected complexity of finding all the numbers out to n that are relatively prime to i is O(n * log(log(log(i)))). Why? Because the average number of distinct prime factors is on average O(log(log(i))). The queue operations are O(log(THAT)) and we do on average O(n) queue operations. (I'm waving my hands past some number theory, but the result is correct.)
OK, what is our alternative to actually enumerating many of the primitive triples?
The answer is to use inclusion-exclusion to count the number below some bound, L Which I will demonstrate by counting the number of primitive triples whose hypotenuse is at most 100.
The first step is to implement a function EvenOddPairCount(L) that counts how many pairs of even/odd numbers there are whose squares sum up to at most L . To do this we traverse the fringe of maximal even/odds. This takes O(sqrt(L)) to traverse. Here is that calculation for 100:
1*1 + 8*8, 4 pairs
3*3 + 8*8, 4 pairs
5*5 + 8*5, 4 pairs
7*7 + 6*6, 3 pairs
9*9 + 2*2, 1 pair
Which gives 16 pairs.
Now the problem is that we have counted things like 3*3 + 6*6 = 45 that are not relatively prime. But we can subtract off EvenOddPairCount(L/9) to find those that are both divisible by 3. We can likewise subtract off EvenOddPairCount(L/25) to find the ones that are divisible by 5. But now the ones divisible by 15 have been added once, and subtracted twice. So we have to add back in EvenOddPairCount(L/(15*15)) to again not count those.
Keep going and you get a sum is over all distinct products x of odd primes of EvenOddPairCount(L/(x*x)) where we add if we had an even number of prime factors (including 0), and subtract if we had an odd number. Since we already have the odd primes, we can easily produce the sequence of inclusion-exclusion terms. It starts off 1, -9, -25, -49, -121, -169, +225, -289, -361, +441 and so on.
But how much work does this take? If l = sqrt(L) it takes l + l/3 + l/5 + l/7 + l/11 + l/13 + l/15 + ... + 1/l < l*(1 + 1/2 + 1/3 + 1/4 + ... + 1/l) = O(l log(l)) = O(sqrt(L) log(L)).
And so we can calculate PrimitiveTriples(L) in time O(sqrt(L) log(L)).
What does this buy us? Well, PrimitiveTriples(N) - PrimitiveTriples(N/2) gives us the number of primitive Pythagorean triples whose hypotenuse is in the range from N/2 to N. And 2*(PrimitiveTriples(N/2) - PrimitiveTriples(N/3)) gives us the number of Pythagorean triples which are multiples of primitive ones in the range from N/3 to N/2. And 3*(PrimitiveTriples(N/3) - PrimitiveTriples(N/4) gives us the number of Pythagorean triples in the range from N/4 to N/3.
Therefore we can enumerate small primitive Pythagorean triples, and figure out how many Pythagorean triples are a multiple of those. And we can use inclusion-exclusion to count the multiples of large Pythagorean triples. Where is the cutoff between the two strategies?
Let's ignore the various log factors for the moment. If we cut off at N^c then we do roughly O(N^c) work on the small. And we need to calculate N^(1-c) thresholds of PrimitiveTriples, the last of which takes work roughly O(N^(c/2)). So let's try setting N^c = N^(1-c) * N^(c/2). That works out when c = (1-c) + c/2 which happens when c = 2/3.
And this is the final algorithm.
Find all primes up to sqrt(N).
Use those primes to enumerate all primitive triples up to O(n^(2/3)) and figure out how many Pythagorean triples they give.
Find all of the inclusion exclusion terms up to N (there are O(sqrt(N)) of them and can be produced directly from the factorization).
Calculate PythagoreanTriples(N/d) for all d up to N^(1/3). Use that to count the rest of the triples.
And all of this runs in time o(N^(2/3 + epsilon)) for any epsilon greater than 0.
You can avoid the GCD calculation altogether:
Make a list of all primes < sqrt(N)
Iterate through all subsets of those primes with total product < sqrt(N)
For each subset, the primes in the set will be "m primes", while the other primes will be "n primes"
Let "m_base" be the product of all m primes
For m, iterate through all combinations of at m primes with product < sqrt(N)/m_base, yielding m = m_base * that combination and:
Calculate the maximum value of n for each m
For n, iterate through all combinations of n primes with product < max
This is a problem given in HackWithInfy2019 in hackerrank.
I am stuck with this problem since yesterday.
Question:
You are given array of N integers.You have to find a pair (i,j)
which maximizes the value of GCD(a[i],a[j])+(j - i)
and 1<=i< j<=n
Constraints are:
2<= N <= 10^5
1<= a[i] <= 10^5
I've tried this problem using python
Here is an approach that could work:
result = 0
min_i = array[1 ... 100000] initialized to 0
for j in [1, 2, ..., n]
for d in divisors of a[j]
let i = min_i[d]
if i > 0
result = max(result, d + j - i)
else
min_i[d] = j
Here, min_i[d] for each d is the smallest i such that a[i] % d == 0. We use this in the inner loop to, for each d, find the first element in the array whose GCD with a[j] is at least d. When j is one of the possible values for which gcd(a[i], a[j]) + j - i is maximal, when the inner loop runs with d equal to the required GCD, result will be set to the correct answer.
The maximum possible number of divisors for a natural number less than or equal to 100,000 is 128 (see here). Therefore the inner loop runs at most 128 * 100,000 = 12.8 million times. I imagine this could pass with some optimizations (although maybe not in Python).
(To iterate over divisors, use a sieve to precompute the smallest nontrivial divisor for each integer from 1 to 100000.)
Here is one way of doing it.
Create a mutable class MinMax for storing the min. and max. index.
Create a Map<Integer, MinMax> for storing the min. and max. index for a particular divisor.
For each value in a, find all divisors for a[i], and update the map accordingly, such that the MinMax object stores the min. and max. i of the number with that particular divisor.
When done, iterate the map and find the entry with largest result of calculating key + value.max - value.min.
The min. and max. values of that entry is your answer.
How can I search through an array and find every combination of three values whose sum is divisible by a given number(x) in java.
In other words, every combination where (n1+n2+n3) % x == 0.
I know this would be a simple solution using a triple for loop but I need something with a time complexity of O(N^2).
Any idea's?
1 - Hash every (element % x) in the list.
2 - Sum every pair of elements in the list (lets call the sum y) and do modded_y = y % x.
3 - Check if x - modded_y is in the hash table. If it is and it's not one of the other 2 numbers then you found a possible combination. Keep iterating and hashing the combinations you found so that they don't repeat.
This is called a meet in the middle strategy.
It's complexity is O(n + (n^2 * 1)) = O(n^2)
I will call the given array A1.
1) create two structs
struct pair{
int first;
int second;
bool valid;
}
struct third{
int value;
int index;
}
2) using a nested loop, initialize an array B1 of all possible Pairs.
3) Loop through B1. if (A1[B1[i].first] + A1[B1[i].second])%x==0 then set B1[i].valid to true
4) create an array A3 of Thirds that stores the index and value of every element from A1 that is divisible by x.
5) using a nested loop, go through each element of A3 and each element of B1. If B1.valid = true
print A1[B1[i].first] and A1[B1[i].second] with an element from A1[A3.index].
that should give you all combinations without using any triple loops.
Another description of the problem: Compute a matrix which satisfies certain constraints
Given a function whose only argument is a 4x4 matrix (int[4][4] matrix), determine the maximal possible output (return value) of that function.
The 4x4 matrix must satisfy the following constraints:
All entries are integers between -10 and 10 (inclusively).
It must be symmetrix, entry(x,y) = entry(y,x).
Diagonal entries must be positive, entry(x,x) > 0.
The sum of all 16 entries must be 0.
The function must only sum up values of the matrix, nothing fancy.
My question:
Given such a function which sums up certain values of a matrix (matrix satisfies above constraints), how do I find the maximal possible output/return value of that function?
For example:
/* The function sums up certain values of the matrix,
a value can be summed up multiple or 0 times. */
// for this example I arbitrarily chose values at (0,0), (1,2), (0,3), (1,1).
int exampleFunction(int[][] matrix) {
int a = matrix[0][0];
int b = matrix[1][2];
int c = matrix[0][3];
int d = matrix[1][1];
return a+b+c+d;
}
/* The result (max output of the above function) is 40,
it can be achieved by the following matrix: */
0. 1. 2. 3.
0. 10 -10 -10 10
1. -10 10 10 -10
2. -10 10 1 -1
3. 10 -10 -1 1
// Another example:
// for this example I arbitrarily chose values at (0,3), (0,1), (0,1), (0,4), ...
int exampleFunction2(int[][] matrix) {
int a = matrix[0][3] + matrix[0][1] + matrix[0][1];
int b = matrix[0][3] + matrix[0][3] + matrix[0][2];
int c = matrix[1][2] + matrix[2][1] + matrix[3][1];
int d = matrix[1][3] + matrix[2][3] + matrix[3][2];
return a+b+c+d;
}
/* The result (max output of the above function) is -4, it can be achieved by
the following matrix: */
0. 1. 2. 3.
0. 1 10 10 -10
1. 10 1 -1 -10
2. 10 -1 1 -1
3. -10 -10 -1 1
I don't know where to start. Currently I'm trying to estimate the number of 4x4 matrices which satisfy the constraints, if the number is small enough the problem could be solved by brute force.
Is there a more general approach?
Can the solution to this problem be generalized such that it can be easily adapted to arbitrary functions on the given matrix and arbitrary constraints for the matrix?
You can try to solve this using linear programming techniques.
The idea is to express the problem as some inequalities, some equalities, and a linear objective function and then call a library to optimize the result.
Python code:
import scipy.optimize as opt
c = [0]*16
def use(y,x):
c[y*4+x] -= 1
if 0:
use(0,0)
use(1,2)
use(0,3)
use(1,1)
else:
use(0,3)
use(0,1)
use(0,1)
use(0,3)
use(0,3)
use(0,2)
use(1,2)
use(2,1)
use(3,1)
use(1,3)
use(2,3)
use(3,2)
bounds=[ [-10,10] for i in range(4*4) ]
for i in range(4):
bounds[i*4+i] = [1,10]
A_eq = [[1] * 16]
b_eq = [0]
for x in range(4):
for y in range(x+1,4):
D = [0]*16
D[x*4+y] = 1
D[y*4+x] = -1
A_eq.append(D)
b_eq.append(0)
r = opt.linprog(c,A_eq=A_eq,b_eq=b_eq,bounds=bounds)
for y in range(4):
print r.x[4*y:4*y+4]
print -r.fun
This prints:
[ 1. 10. -10. 10.]
[ 10. 1. 8. -10.]
[-10. 8. 1. -10.]
[ 10. -10. -10. 1.]
16.0
saying that the best value for your second case is 16, with the given matrix.
Strictly speaking you are wanting integer solutions. Linear programming solves this type of problem when the inputs can be any real values, while integer programming solves this type when the inputs must be integers.
In your case you may well find that the linear programming method already provides integer solutions (it does for the two given examples). When this happens, it is certain that this is the optimal answer.
However, if the variables are not integral you may need to find an integer programming library instead.
Sort the elements in the matrix in descending order and store in an array.Iterate through the elements in the array one by one
and add it to a variable.Stop iterating at the point when adding an element to variable decrease its value.The value stored in the variable gives maximum value.
maxfunction(matrix[][])
{
array(n)=sortDescending(matrix[][]);
max=n[0];
i=1;
for i to n do
temp=max;
max=max+n[i];
if(max<temp)
break;
return max;
}
You need to first consider what matrices will satisfy the rules. The 4 numbers on the diagonal must be positive, with the minimal sum of the diagonal being 4 (four 1 values), and the maximum being 40 (four 10 values).
The total sum of all 16 items is 0 - or to put it another way, sum(diagnoal)+sum(rest-of-matrix)=0.
Since you know that sum(diagonal) is positive, that means that sum(rest-of-matrix) must be negative and equal - basically sum(diagonal)*(-1).
We also know that the rest of the matrix is symmetrical - so you're guaranteed the sum(rest-of-matrix) is an even number. That means that the diagonal must also be an even number, and the sum of the top half of the matrix is exactly half the diagonal*(-1).
For any given function, you take a handful of cells and sum them. Now you can consider the functions as fitting into categories. For functions that take all 4 cells from the diagonal only, the maximum will be 40. If the function takes all 12 cells which are not the diagonal, the maximum is -4 (negative minimal diagonal).
Other categories of functions that have an easy answer:
1) one from the diagonal and an entire half of the matrix above/below the diagonal - the max is 3. The diagonal cell will be 10, the rest will be 1, 1, 2 (minimal to get to an even number) and the half-matrix will sum at -7.
2) two cells of the diagonal and half a matrix - the max is 9. the two diagonal cells are maximised to two tens, the remaining cells are 1,1 - and so the half matrix sums at -11.
3) three cells from the diagonal and half a matrix - the max is 14.
4) the entire diagonal and half the matrix - the max is 20.
You can continue with the categories of selecting functions (using some from the diagonal and some from the rest), and easily calculating the maximum for each category of selecting function. I believe they can all be mapped.
Then the only step is to put your new selecting function in the correct category and you know the maximum.
I realize permutations in programming language is a very frequently asked question, however I feel like my question is sort of unique.
I have received input of a certain length integer N and stored each digit in an array where the index of the array stores the number of times that digit occurs in N.
now I want to test if some function holds true with all permutations of N's original length with no leading zeroes. Ex:
int[] digits = new int[10];
String n = "12345675533789025";
for (char c : n.toCharArray())
digits[c-'0']++;
for (Long f : allPermutationsOf(digits))
if (someCondition(f))
System.out.println(f);
a precondition to the following code is that N must be less than 2^64-1, (long's maximum value.)
The question is, how would I take all permutations of the digits array and return a Long[] or long[] without using some kind of String concatenation? Is there a way to return a long[] with all permutations of digits[] in the "Integer scope of things" or rather using only integer arithmetic?
To elaborate on one of the above comments, putting a digit d in a given place in the resulting long is easy: d*1 puts it in the 1s place, d*1000 puts it in the thousands place, and in general d * (10^k) puts d into the k+1th digit. You have N total digits to fill, so you need to do permutations on the powers of 10 from 1 to 10^(N-1).
If you are expecting the permutations to be Longs anyway, instead of representing n as an array of counts, it might be easier to represent it as a Long too.
Here are a couple of ways you can generate the permutations.
Think of generating permutations as finding the next largest number with the same set of digits, starting from the number consisting of the sorted digits of n. In this case, the answers to this StackOverflow question is helpful. You can use arithmetic operations and modding instead of string concatenation to implement the algorithm there (I can provide more details if you like). A benefit of this is that the permutations you generate will automatically be in order.
If you don't care about the order of the permutations and you expect the number of digit duplicates to be small, you can use the Steinhaus-Johnson-Trotter algorithm, which (according to Robert Sedgewick) is the fastest algorithm for generating permutations of unique elements. To make sure duplicate permutations are not generated, you would have to distinguish every duplicate digit and only emit the permutations where they appear in order (i.e., if 2 appears three times, then create the elements 2_1, 2_2, 2_3 and make sure those three elements always appear in that order in an emitted permutation).
For the requirement, assuming that the length of N is n, we can generate all permutations by going from digit to digit, starting from 0 and end at n - 1. With 0 is the leading digit.
For each digit, we only go through each possibility (0 to 9) once , which will avoid duplicate permutation.
From digit x to digit x + 1, we can easily generate the current value by passing a number called current
For example: at digit 3, we have current = 1234, so at digit 4, if we choose 5 to be at digit 4, the current will be 1234*10 + 5 = 12345
Sample code in Java:
public void generate(int index, int length, int[] digits, long current, ArrayList<Long> result) {
//All the permutation will be stored in result ArrayList
for (int i = 0; i < 10; i++) {
if (digits[i] > 0 && (i != 0 || index != 0)) {
digits[i]--;
if (index + 1 == length) {//If this is the last digit, add its value into result
result.add(current * 10 + i);
} else {//else, go to next digit
generate(index + 1, length, digits, current * 10 + i, result);
}
digits[i]++;
}
}
}