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 1 year ago.
Improve this question
I have an array of even number of elements, I have to select n/2( n=array size), pairs and calculate their GCD such that the sum of their GCD is max, given once we use those elements from array, we cannot use them again.
Example1: `
Input : 8 24 12 16
Output : 20
Explanation: We select two pairs (8,16) and (12,24) as sum of their GCD is maximum.
If we choose some other pairs, say (8,12) and (24,16), sum of their GCD will be 4+4 =8.
Example 2:
Input : 12 10 36 25 36 16
Output: 45
Explanation: We select the following 3 pairs : (36,36), (10,25) and (12,16) as the sum of their GCD is
36+5+4 = 45.
Our Approach:
for i in range(0,n):
max = 0;
for j in range(i+1,n):
temp = gcd(a[i], a[j]) // standard func to find GCD
if(max<temp):
store i and j
store max gcd every time and finally make a[i] and a[j] =0 to mark the visited elements
Edited
Constraint: max number of elements = 20, a[i]< 10^9.
Can you suggest an algorithm to optimally satisfy the above testcases in the least time complexity?
Because my approach is failing on multiple testcases.
This is a comment but I am not allowed to post comment yet.
It is not good to solve this problem by looking for the largest gcd.
Take [8,9,24,36], the largest gcd is gcd(24,36) = 12, that will get you gcd(24,36) + gcd(8,9) = 12+1 =13.
However, the largest sum is given by gcd(8,24) + gcd(9,36) = 8+9 = 17.
Related
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 3 years ago.
Improve this question
This is my attempt to find a well performing algorithm for problem 5 Project Euler - find the smalles possible number that is evenly divisible x and all the numbers below x.
I've tried using one loop make #s and another to test if that number is evenly divisible by x and all #s below x
System.out.println("This program finds the smallest positive "
+ "number that");
System.out.println("is evenly divisible by all of the numbers "
+ "from 1 to N.");
System.out.print("Enter N: ");
int N=kb.nextInt();
long bigN=1;
for(int i=1;i<=N;i++){
bigN=bigN*i;
/*bigN serves as a definite end for our loop
when trying to find all #s divisible from 1 to n
*/
}
long smallestAnswer=bigN;
int count=0;
for(long i=1;i<=bigN;i++){//# being tested
for(int j=1;j<=N;j++){//test
if(i%j==0){
count++;
}
if(count==N && i<smallestAnswer){
smallestAnswer=i;//should catch only the first/smallest answer
break;
}
}
count=0;
}
System.out.printf("\nThe smallest # evenly divisible by all of the "
+ "numbers from 1 to N");
System.out.printf("\nis %,d\n",smallestAnswer);
}
The code works. No run/compileTime errors. It's just far too slow. If the user enters a # bigger than 11, the code just freezes basically
You are using a brute-force algorithm. Challenges, like found on Project Euler, are more often challenges to find the right algorithm, not merely challenges to write the code.
The challenge here is to find the least common multiple (see Wikipedia), of all the numbers from 1 to X.
Example: If X is 10, one way to solve it is to identify the divisors:
1 = 1
2 = 2
3 = 3
4 = 2^2
5 = 5
6 = 2 * 3
7 = 7
8 = 2^3
9 = 3^2
10 = 2 * 5
The divisors for the least common multiple is therefore:
1 * 2^3 * 3^2 * 5 * 7 = 1 * 8 * 9 * 5 * 7 = 2520
Since this is a challenge for you to solve, I'll leave the coding to you.
I'm not quite sure why you're struggling with performance.
$ date && X 20 && date
Tue Jun 25 13:18:13 CDT 2019
N: 20
232792560 is divisible by all numbers 1 to 20
Tue Jun 25 13:18:16 CDT 2019
3 seconds for N == 20.
You are doing extra math for each number you check -- a LOT of extra math. Instead of doing the check for each number 1 to N, first, you could do from 2 to N, as all numbers are divisible by 1. But more importantly, you're doing ALL even if one fails. If you turn that portion around, breaking out of your "does this number work" code as soon as a modulus check fails. On N=20, this will save you 18 checks on all odd numbers.
You could also gain more improvements. The number must be even. So if n>1, you could start at 2 and increment by 2 instead of one. If n>=3, you could actually start at 6 and increment by 6, saving a LOT of math. And if n>=4, you could start at 12 and increment by 12.
For reference, here is my implementation.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char **argv) {
int n = atoi(argv[1]);
long trying = 1;
bool found = false;
while(!found) {
found = true;
++trying;
for (long checkDivide = 2; checkDivide <= n; +checkDivide) {
if (trying % checkDivide != 0) {
found = false;
break;
}
}
}
printf("%ld is divisible by all numbers 1 to %d\n", trying, n);
return 0;
}
I skipped asking for input and just put the value on the command line.
Note that reversing the check also is probably more efficient. That is, start checking at n and work down to 2. X % 20 is going to fail more often than X % 2. I'm not using sufficient time check resolution to be sure how much more efficient it is.
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 5 years ago.
Improve this question
for(i=0;i<k;i++)
{
l=sc.nextLong();
r=sc.nextLong();
v=sc.nextLong();
for(j=l-1;j<r;j++)
{
m=(int)j;
ar[m]=ar[m]+(long)v;
}
}
I'm solving a competitive programming question and I need to optimise this nested for loop to a single for loop. Code should have execution time below 2secs, this one takes 2 secs. Here k,l,r,v can be int values in the range 0 to 10^9.
I don't think you can avoid two loops, but you can make it sequential, instead of nested.
long[] delta = new long[ar];
for(i=0;i<k;i++)
{
l=sc.nextLong();
r=sc.nextLong();
v=sc.nextLong();
if (l-1 < r) {
m=(int)(l-1);
delta[m] = v;
m=(int)r;
if (m < delta.length) {
delta[m] = -v;
}
}
}
long cumulative = 0;
for (int a = 0; a < ar.length; ++a) {
cumulative += delta[a];
ar[a] += cumulative;
}
Rather than keeping on incrementing the values in delta for each of the l,r ranges, this just stores a "delta" array: this stores a +v at the index where you'd start incrementing the array by v; and -v at the index where you'd stop. So, recording that the range between l and r should be incremented by v is now an O(1) operation, rather than an O(r-l) operation.
So, some portion of this array looks like:
2
0 0 0 0 0 0 0 0 0 0
-2
(I'm just vertically shifting the 2s to make it clearer)
If you calculate the cumulative sum of these elements:
2 2 2 2 2 2
0 0 0 0 0 0
In other words, you can show a range where you are going to increment by 2 by storing just the start and end positions of this range.
This is what the cumulative variable stores: it's just the sum of all the elements in the delta array to the left of and including the current position. And that's the amount to increment the corresponding element of ar by.
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 8 years ago.
Improve this question
I am really struggling with this recursive question. Can anyone help me solve the recurrence T(n) = 5T (n/5)+5 with the base condition T(1) = 0 via closed-form formula? It is given that n = 5^m with the integer m = log5 n.
It will be sufficient to compute T(5n) for n >= 0. For all other values of x, T(x) will equal T(y) where y is the largest power of 5 smaller than x, since the calculations are the same. (I'm assuming that when you write n/5 you mean integer division, i.e. floor(n/5).)
Then:
T(50) = 0
T(51) = 5 * 0 + 5 = 5
T(52) = 5 * 5 + 5 = 52 + 51
T(53) = 5 * (5 * 5 + 5) + 5 = 53 + 52 + 51
... which leads to:
T(5n) = 5n + 5n-1 + ... + 52 + 51
which, using a high-school algebra formula (sum of a geometric series), is
T(5n) = (5n+1 - 5) / 4
If you're thinking about time complexity, notice that T(x) will always be less than or equal to 5x / 4. And since we don't worry about constant factors when expressing things in O-notation, this essentially means T(x) = O(x).
A non constructive way to solve this: looking a bit at the formula one guesses that T(5m) = (5m+1-5)/4. This can be shown by induction:
it is correct for m=0: T(1) = 0
assuming it is correct for m we show it for m+1: T(5m+1) = T(5*5m) = 5T(5m)+5 = 5*((5m+1-5)/4)+5 = (5m+2-25)/4+5 = (5m+2-5)/4.
Therefore it is correct for all m.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Closed 9 years ago.
Improve this question
Good evening
i'm trying to solve a question which is :
You are given a int[] marks containing the grades you have received so far in a class. Each
grade is between 0 and 10, inclusive. Assuming that you will receive a 10 on all future
assignments, determine the minimum number of future assignments that are needed for you to
receive a final grade of 10. You will receive a final grade of 10 if your average grade is 9.5 or
higher.
Definition Class: AimToTen Method: need Parameters:
int[] Returns: int Method signature: int need(int[]
marks) (be sure your method is public) Examples 1)
{9, 10, 10, 9} Returns: 0 Your average is already 9.5, so no
future assignments are needed. 2) {8, 9} Returns:
4 In this case you need 4 more assignments. With each
completed assignment, your average could increase to 9, 9.25, 9.4
and 9.5, respectively
My attempt to solve is :
public int need(int[] marks) {
int i=0, sum = 0, avg = 0, k = 0, counter = 0, ToCompleteMarks[] = null;
for (i; i < marks.length; i++) {
sum = sum + marks[i];
ToCompleteMarks[i] = marks[i] + ToCompleteMarks[i];// To copy the array so when i add 10 later to the program the original array does not change > good ?
}
avg = sum / marks.length;
while (avg < 9.5)
ToCompleteMarks[i]; //I need to add the number 10 to the array then get back to calculate the avg . But no ideas how to do that ! .
counter++;
return counter;
}
if you could help me with that I would be really greatful
thanks
We can do the below mentioned steps:
1. Get the difference between the avg calculated and the desired average(9.5)
LEts say that the calculated average is 8.
Difference would be 9.5-8 = 1.5
Hence we can take the upper limit(ceiling value) of the difference using Math.ceil(difference). Here it would be 2. Thus we need to add two assignments to the array.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
My job is to generate and urban residents using normal probability distribution.
Number of cities, 3000, Population 15 000 000
(in JAVA)
int people = 15000000;
int[] arrayofcity = new int[3000]
for (int i = 0; i < arrayofcity.length; i++) {
//how to generate people to the towns of total
//nextGaussian()??
}
Thank you for your help
Try something like this.. Not very efficient as the distributions are averaged/cancelled for every 2 values.
int people = 15000000;
int[] arrayofcity = new int[3000];
int sharedSpread=people/3000; // sharedSpread= avg population
for (int i = 0; i < arrayofcity.length; i++) {
if(i%2!=0)
arrayOfCity[i] = sharedSpread + (sharedSpread-arrayOfCity[i-1]);
else
{
Random r = new Random();
int val = Random.nextInt();
arrayOfCity[i] = val%sharedSpread ;
}
}
PS: This is not the exact code, but this can show how to go about the problem.. You can change the frequency of distribution . Instead of 2 here, we can change it to 4 to get better random distributions...
A rough sketch of a method:
Use Random#nextGaussian() to create a value X between 0-1 for each city.
Calculate the sum of all these X values. Call it S.
For each city, take its value X and divide by S. Multiply this result by the total population (15 000 000). This is how many people live in this city.
Note that this would be tricky to implement in practice due to rounding. As such, the total population may be slightly above/below the desired 15 000 000, so some method will be needed to add/remove the extra people.
One (non efficient, but beautiful mathematically IMO) way to do it is:
For each person (repeat 15M times), choose with uniform distribution
his city.
It will give you a total sum of 15M people in all cities, and according to central limit theorem - you will get close to normal distributionin in each city, because each city is basically a sum of Bernoulli trials with p=1/3000, over 15M trials.