why am I getting seg fault in this? - c++

Problem Statement
Mark is an undergraduate student and he is interested in rotation. A conveyor belt competition is going on in the town which Mark wants to win. In the competition, there's A conveyor belt which can be represented as a strip of 1xN blocks. Each block has a number written on it. The belt keeps rotating in such a way that after each rotation, each block is shifted to left of it and the first block goes to last position.
There is a switch near the conveyer belt which can stop the belt. Each participant would be given a single chance to stop the belt and his PMEAN would be calculated.
PMEAN is calculated using the sequence which is there on the belt when it stops. The participant having highest PMEAN is the winner. There can be multiple winners.
Mark wants to be among the winners. What PMEAN he should try to get which guarantees him to be the winner.
Definitions
PMEAN = (Summation over i = 1 to n) (i * i th number in the list)
where i is the index of a block at the conveyor belt when it is stopped. Indexing starts from 1.
Input Format
First line contains N denoting the number of elements on the belt.
Second line contains N space separated integers.
Output Format
Output the required PMEAN
Constraints
1 ≤ N ≤ 10^6
-10^9 ≤ each number ≤ 10^9
Code
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main (void)
{
int n;
cin>>n;
vector <int> foo;
int i = 0,j = 0,k,temp,fal,garb=0;
while (i < n)
{
cin>>fal;
foo.push_back(fal);
i++;
}
vector<int> arr;
//arr.reserve(10000);
for ( i = 0; i < n; i++ )
{
garb = i+1;
arr.push_back(garb);
}
long long product = 0;
long long bar = 0;
while (j < n)
{
i = 0;
temp = foo[0];
while ( i < n-1 )
{
foo[i] = foo[i+1];
i++;
}
foo[i] = temp;
for ( k = 0; k < n; k++ )
bar = bar + arr[k]*foo[k];
if ( bar > product )
product = bar;
j++;
}
return 0;
}
My Question:
What I am doing is basically trying out different combinations of the original array and then multiplying it with the array containing the values 1 2 3 ...... and then returning the maximum value. However, I am getting a segmentation fault in this.
Why is that happening?

Here's some of your code:
vector <int> foo;
int i = 0;
while (i < n)
{
cin >> fal;
foo[i] = fal;
i++;
}
When you do foo[0] = fal, you cause undefined behavior. There's no room in foo for [0] yet. You probably want to use std::vector::push_back() instead.
This same issue also occurs when you work on vector<int> arr;
And just as an aside, people will normally write that loop using a for-loop:
for (int i=0; i<n; i++) {
int fal;
cin >> fal;
foo.push_back(fal);
}
With regards to the updated code:
You never increment i in the first loop.
garb is never initialized.

Related

Bug in the 0-1 Knapsack code. What is the error in my code?

I was solving this problem in geeksforgeeks in the practice part but this code fails somewhere I don't understand
#include <iostream>
using namespace std;
int main() {
//code
int T,N,W;
cin>>T;//The number of test cases
while(T-->0){
cin>>N>>W;//N for number of items and W for capacity
int dyna[N+1][W+1] = {{0,0}};//table to store values
int val[N+1],wt[N+1];//val stores value and wt for weight
for(int i = 1;i <= N;i++)cin>>val[i];
for(int i = 1;i <= N;i++)cin>>wt[i];
for(int i = 0;i <=N;i++){
for(int j = 0;j <= W;j++){
if(i==0||j==0)dyna[i][j]=0;
else if(wt[i]<=W)
dyna[i][j] = max(dyna[i-1][j],val[i]+dyna[i-1][j-wt[i]]);
else
dyna[i][j] = dyna[i-1][j];
}
}
cout<<dyna[N][W]<<endl;
}
return 0;
}
For one, you have separate N and W lengths, which is redundant as these should always be equal. I think the problem you are observing, though, is with your else if. You check if the current weight is less than the number of items, which doesn't really make sense. It should probably be something like else if(j-wt[i]>=0), since you are trying to determine if you can subtract the current weight wt[i] from the current sum j and get a valid (in bounds) result. I imagine you are getting a segfault or similar because you are trying to access dyna[i-1][j-wt[i]] when, for instance, i and j are 1 and wt[i] is 10, as dyna[0][-9] is (probably) unalloced memory.

How to efficiently find coefficients of a polynomial from its roots? [duplicate]

This question already has answers here:
Sum of multiplication of all combination of m element from an array of n elements
(3 answers)
Closed 7 years ago.
Given are the n roots of a polynomial whose leading coefficient is 1.
How do I efficiently find out the coefficients of this polynomial?
Mathematically,
I know that if the first coefficient is 1, then sum of product roots taken k at a time will be the k+1-th coefficient of the polynomial.
My code is based on this approach.
In other words, how to optimally find the sum of product of numbers from a list taken k at a time.
int main()
{
int n, sum;
cin >> n;
int a[n];
for (int i=0; i<n; i++) cin >> a[i];
//for the second coefficient
sum=0;
for (int i=0; i<n; i++)
{
sum+=a[i];
}
cout << sum << endl;
//for the third coefficient
sum=0;
for (int i=0; i<n; i++)
{
for (int j=i+1; j<n; j++)
{
sum+=a[i]*a[j];
}
}
cout << sum << endl;
}
I have thought of marking the numbers on whether I have taken them into the product or not for the purpose of higher coefficients, but have not written the code for it as it is practically of no use if the degree of polynomial is large.
You need to compute the product of linear factors
(x-z1)·(x-z2)·…·(x-zn)
This can be implemented inductively by repeatedly multiplying a polynomial with a linear factor
(a[0]+a[1]·x+…+a[m-1]·x^(m-1))·(x-zm)
= (-a[0]·zm) + (a[0]-a[1]·zm)·x + … + (a[m-2]-a[m-1]·zm) ·x^(m-1) + a[m-1]·x^m
In place this can be implemented as loop
a[m] = a[m-1]
for k = m-1 downto 1
a[k] = a[k-1] - a[k]*zm
end
a[0] = -a[0]*zm
This gives a total of n²/2 multiplications and a like number of subtractions for the multiplication of all n linear factors.
First of all in C++ a[n] is a static array, so compiler need to know n during compile time, which is not the case here. So the code is "not correct" in C++. I know it will compile in gcc or other compilers, but it is against C++ standard. See C++ declare an array based on a non-constant variable? What you need here is a dynamic array, using new and delete command, or you can use more safe std::vector class from STL.
Now, the main problem here is that you need k nested loops, if you want to calculate k'th coefficients, (I am assuming 1 is 0th coefficient, not 1st, just convention). So, you need to implement variable no. of nested for loops in your code. I am posting the solution of your problem, in which I used a method to implement variable no. of nested for loops. Hope this will solve your problem.
#include <iostream>
#include <cmath>
#include <vector> // include vector class
using namespace std;
double coeff(int,const vector<double>& ); // function declaration to to calculate coefficients
int main()
{
int N = 5; // no. of roots
// dynamic vector containing values of roots
vector<double> Roots(N);
for(int i = 0 ; i<N ; ++i)
Roots[i] = (double)(i+1); // just an example, you can use std::cin
int K = 2; // say you want to know K th coefficient of the polynomial
double K_th_coeff = coeff(K,Roots); // function call
cout<<K_th_coeff<<endl; // print the value
return 0;
}
double coeff(int k,const vector<double>& roots)
{
int size = roots.size(); // total no. of roots
int loop_no = k; // total no. of nested loops
vector<int> loop_counter(loop_no+1); // loop_counter's are the actual iterators through the nested loops
// like i_1, i_2, i_3 etc., loop_counter[loop_no] is needed to maintain the condition of the loops
for(int i=0; i<loop_no+1; ++i)
loop_counter[i]=0; // initialize all iterators to zero
vector<int> MAX(loop_no+1); // MAX value for a loop, like for(int i_1=0; i_1 < MAX[1]; i++)...
for(int i=0 ; i<loop_no ; ++i)
MAX[i] = size - loop_no + i + 1; // calculated from the algorithm
MAX[loop_no]=2; // do'es no matter, just != 1
int p1=0; // required to maintain the condition of the loops
double sum(0); // sum of all products
while(loop_counter[loop_no]==0)
{
// variable nested loops starts here
int counter(0);
// check that i_1 < i_2 < i_3 ....
for(int i = 1 ; i < loop_no; ++i)
{
if(loop_counter[i-1] < loop_counter[i])
++counter;
}
if(counter == loop_no - 1) // true if i_1 < i_2 < i_3 ....
{
double prod(1);
for(int i = 0 ; i < loop_no ; ++i)
prod *= roots[loop_counter[i]]; // taking products
sum += prod; // increament
}
// variable nested loops ends here...
++loop_counter[0];
while(loop_counter[p1]==MAX[p1])
{
loop_counter[p1]=0;
loop_counter[++p1]++;
if(loop_counter[p1]!=MAX[p1])
p1=0;
}
}
return pow(-1.0,k)*sum; // DO NOT FORGET THE NEGATIVE SIGN
}
I have checked the code, and it is working perfectly. If you want to know how to implement variable no.of nested for loops, just visit variable nested for loops and see BugMeNot2013's answer.

Count number of ways for choosing two numbers in efficient algorithm

I solved this problem but I got TLE Time Limit Exceed on online judge
the output of program is right but i think the way can be improved to be more efficient!
the problem :
Given n integer numbers, count the number of ways in which we can choose two elements such
that their absolute difference is less than 32.
In a more formal way, count the number of pairs (i, j) (1 ≤ i < j ≤ n) such that
|V[i] - V[j]| < 32. |X|
is the absolute value of X.
Input
The first line of input contains one integer T, the number of test cases (1 ≤ T ≤ 128).
Each test case begins with an integer n (1 ≤ n ≤ 10,000).
The next line contains n integers (1 ≤ V[i] ≤ 10,000).
Output
For each test case, print the number of pairs on a single line.
my code in c++ :
int main() {
int T,n,i,j,k,count;
int a[10000];
cin>>T;
for(k=0;k<T;k++)
{ count=0;
cin>>n;
for(i=0;i<n;i++)
{
cin>>a[i];
}
for(i=0;i<n;i++)
{
for(j=i;j<n;j++)
{
if(i!=j)
{
if(abs(a[i]-a[j])<32)
count++;
}
}
}
cout<<count<<endl;
}
return 0;
}
I need help how can I solve it in more efficient algorithm ?
Despite my previous (silly) answer, there is no need to sort the data at all. Instead you should count the frequencies of the numbers.
Then all you need to do is keep track of the number of viable numbers to pair with, while iterating over the possible values. Sorry no c++ but java should be readable as well:
int solve (int[] numbers) {
int[] frequencies = new int[10001];
for (int i : numbers) frequencies[i]++;
int solution = 0;
int inRange = 0;
for (int i = 0; i < frequencies.length; i++) {
if (i > 32) inRange -= frequencies[i - 32];
solution += frequencies[i] * inRange;
solution += frequencies[i] * (frequencies[i] - 1) / 2;
inRange += frequencies[i];
}
return solution;
}
#include <bits/stdc++.h>
using namespace std;
int a[10010];
int N;
int search (int x){
int low = 0;
int high = N;
while (low < high)
{
int mid = (low+high)/2;
if (a[mid] >= x) high = mid;
else low = mid+1;
}
return low;
}
int main() {
cin >> N;
for (int i=0 ; i<N ; i++) cin >> a[i];
sort(a,a+N);
long long ans = 0;
for (int i=0 ; i<N ; i++)
{
int t = search(a[i]+32);
ans += (t -i - 1);
}
cout << ans << endl;
return 0;
}
You can sort the numbers, and then use a sliding window. Starting with the smallest number, populate a std::deque with the numbers so long as they are no larger than the smallest number + 31. Then in an outer loop for each number, update the sliding window and add the new size of the sliding window to the counter. Update of the sliding window can be performed in an inner loop, by first pop_front every number that is smaller than the current number of the outer loop, then push_back every number that is not larger than the current number of the outer loop + 31.
One faster solution would be to first sort the array, then iterate through the sorted array and for each element only visit the elements to the right of it until the difference exceeds 31.
Sorting can probably be done via count sort (since you have 1 ≤ V[i] ≤ 10,000). So you get linear time for the sorting part. It might not be necessary though (maybe quicksort suffices in order to get all the points).
Also, you can do a trick for the inner loop (the "going to the right of the current element" part). Keep in mind that if S[i+k]-S[i]<32, then S[i+k]-S[i+1]<32, where S is the sorted version of V. With this trick the whole algorithm turns linear.
This can be done constant number of passes over the data, and actually can be done without being affected by the value of the "interval" (in your case, 32).
This is done by populating an array where a[i] = a[i-1] + number_of_times_i_appears_in_the_data - informally, a[i] holds the total number of elements that are smaller/equals to i.
Code (for a single test case):
static int UPPER_LIMIT = 10001;
static int K = 32;
int frequencies[UPPER_LIMIT] = {0}; // O(U)
int n;
std::cin >> n;
for (int i = 0; i < n; i++) { // O(n)
int x;
std::cin >> x;
frequencies[x] += 1;
}
for (int i = 1; i < UPPER_LIMIT; i++) { // O(U)
frequencies[i] += frequencies[i-1];
}
int count = 0;
for (int i = 1; i < UPPER_LIMIT; i++) { // O(U)
int low_idx = std::max(i-32, 0);
int number_of_elements_with_value_i = frequencies[i] - frequencies[i-1];
if (number_of_elements_with_value_i == 0) continue;
int number_of_elements_with_value_K_close_to_i =
(frequencies[i-1] - frequencies[low_idx]);
std::cout << "i: " << i << " number_of_elements_with_value_i: " << number_of_elements_with_value_i << " number_of_elements_with_value_K_close_to_i: " << number_of_elements_with_value_K_close_to_i << std::endl;
count += number_of_elements_with_value_i * number_of_elements_with_value_K_close_to_i;
// Finally, add "duplicates" of i, this is basically sum of arithmetic
// progression with d=1, a0=0, n=number_of_elements_with_value_i
count += number_of_elements_with_value_i * (number_of_elements_with_value_i-1) /2;
}
std::cout << count;
Working full example on IDEone.
You can sort and then use break to end loop when ever the range goes out.
int main()
{
int t;
cin>>t;
while(t--){
int n,c=0;
cin>>n;
int ar[n];
for(int i=0;i<n;i++)
cin>>ar[i];
sort(ar,ar+n);
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
if(ar[j]-ar[i] < 32)
c++;
else
break;
}
}
cout<<c<<endl;
}
}
Or, you can use a hash array for the range and mark occurrence of each element and then loop around and check for each element i.e. if x = 32 - y is present or not.
A good approach here is to split the numbers into separate buckets:
constexpr int limit = 10000;
constexpr int diff = 32;
constexpr int bucket_num = (limit/diff)+1;
std::array<std::vector<int>,bucket_num> buckets;
cin>>n;
int number;
for(i=0;i<n;i++)
{
cin >> number;
buckets[number/diff].push_back(number%diff);
}
Obviously the numbers that are in the same bucket are close enough to each other to fit the requirement, so we can just count all the pairs:
int result = std::accumulate(buckets.begin(), buckets.end(), 0,
[](int s, vector<int>& v){ return s + (v.size()*(v.size()-1))/2; });
The numbers that are in non-adjacent buckets cannot form any acceptable pairs, so we can just ignore them.
This leaves the last corner case - adjacent buckets - which can be solved in many ways:
for(int i=0;i<bucket_num-1;i++)
if(buckets[i].size() && buckets[i+1].size())
result += adjacent_buckets(buckets[i], buckets[i+1]);
Personally I like the "occurrence frequency" approach on the one bucket scale, but there may be better options:
int adjacent_buckets(const vector<int>& bucket1, const vector<int>& bucket2)
{
std::array<int,diff> pairs{};
for(int number : bucket1)
{
for(int i=0;i<number;i++)
pairs[i]++;
}
return std::accumulate(bucket2.begin(), bucket2.end(), 0,
[&pairs](int s, int n){ return s + pairs[n]; });
}
This function first builds an array of "numbers from lower bucket that are close enough to i", and then sums the values from that array corresponding to the upper bucket numbers.
In general this approach has O(N) complexity, in the best case it will require pretty much only one pass, and overall should be fast enough.
Working Ideone example
This solution can be considered O(N) to process N input numbers and constant in time to process the input:
#include <iostream>
using namespace std;
void solve()
{
int a[10001] = {0}, N, n, X32 = 0, ret = 0;
cin >> N;
for (int i=0; i<N; ++i)
{
cin >> n;
a[n]++;
}
for (int i=0; i<10001; ++i)
{
if (i >= 32)
X32 -= a[i-32];
if (a[i])
{
ret += a[i] * X32;
ret += a[i] * (a[i]-1)/2;
X32 += a[i];
}
}
cout << ret << endl;
}
int main()
{
int T;
cin >> T;
for (int i=0 ; i<T ; i++)
solve();
}
run this code on ideone
Solution explanation: a[i] represents how many times i was in the input series.
Then you go over entire array and X32 keeps track of number of elements that's withing range from i. The only tricky part really is to calculate properly when some i is repeated multiple times: a[i] * (a[i]-1)/2. That's it.
You should start by sorting the input.
Then if your inner loop detects the distance grows above 32, you can break from it.
Thanks for everyone efforts and time to solve this problem.
I appreciated all Attempts to solve it.
After testing the answers on online judge I found the right and most efficient solution algorithm is Stef's Answer and AbdullahAhmedAbdelmonem's answer also pavel solution is right but it's exactly same as Stef solution in different language C++.
Stef's code got time execution 358 ms in codeforces online judge and accepted.
also AbdullahAhmedAbdelmonem's code got time execution 421 ms in codeforces online judge and accepted.
if they put detailed explanation to there algorithm the bounty will be to one of them.
you can try your solution and submit it to codeforces online judge at this link after choosing problem E. Time Limit Exceeded?
also I found a great algorithm solution and more understandable using frequency array and it's complexity O(n).
in this algorithm you only need to take specific range for each inserted element to the array which is:
begin = element - 32
end = element + 32
and then count number of pair in this range for each inserted element in the frequency array :
int main() {
int T,n,i,j,k,b,e,count;
int v[10000];
int freq[10001];
cin>>T;
for(k=0;k<T;k++)
{
count=0;
cin>>n;
for(i=1;i<=10000;i++)
{
freq[i]=0;
}
for(i=0;i<n;i++)
{
cin>>v[i];
}
for(i=0;i<n;i++)
{
count=count+freq[v[i]];
b=v[i]-31;
e=v[i]+31;
if(b<=0)
b=1;
if(e>10000)
e=10000;
for(j=b;j<=e;j++)
{
freq[j]++;
}
}
cout<<count<<endl;
}
return 0;
}
finally i think the best approach to solve this kind of problems to use frequency array and count number of pairs in specific range because it's time complexity is O(n).

Trouble sieving primes from a large range

#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
int main() {
int t,m,n;
scanf("%d",&t);
while(t--)
{
scanf("%d %d",&m,&n);
int rootn=sqrt(double(n));
bool p[10000]; //finding prime numbers from 1 to square_root(n)
for(int j=0;j<=rootn;j++)
p[j]=true;
p[0]=false;
p[1]=false;
int i=rootn;
while(i--)
{
if(p[i]==true)
{
int c=i;
do
{
c=c+i;
p[c]=false;
}while(c+p[i]<=rootn);
}
};
i=0;
bool rangep[10000]; //used for finding prime numbers between m and n by eliminating multiple of primes in between 1 and squareroot(n)
for(int j=0;j<=n-m+1;j++)
rangep[j]=true;
i=rootn;
do
{
if(p[i]==true)
{
for(int j=m;j<=n;j++)
{
if(j%i==0&&j!=i)
rangep[j-m]=false;
}
}
}while(i--);
i=n-m;
do
{
if(rangep[i]==true)
printf("%d\n",i+m);
}while(i--);
printf("\n");
}
return 0;
system("PAUSE");
}
Hello I'm trying to use the sieve of Eratosthenes to find prime numbers in a range between m to n where m>=1 and n<=100000000. When I give input of 1 to 10000, the result is correct. But for a wider range, the stack is overflowed even if I increase the array sizes.
               
A simple and more readable implementation
void Sieve(int n) {
int sqrtn = (int)sqrt((double)n);
std::vector<bool> sieve(n + 1, false);
for (int m = 2; m <= sqrtn; ++m) {
if (!sieve[m]) {
cout << m << " ";
for (int k = m * m; k <= n; k += m)
sieve[k] = true;
}
}
for (int m = sqrtn; m <= n; ++m)
if (!sieve[m])
cout << m << " ";
}
Reason of getting error
You are declaring an enormous array as a local variable. That's why when the stack frame of main is pushed it needs so much memory that stack overflow exception is generated. Visual studio is tricky enough to analyze the code for projected run-time stack usage and generate exception when needed.
Use this compact implementation. Moreover you can have bs declared in the function if you want. Don't make implementations complex.
Implementation
typedef long long ll;
typedef vector<int> vi;
vi primes;
bitset<100000000> bs;
void sieve(ll upperbound) {
_sieve_size = upperbound + 1;
bs.set();
bs[0] = bs[1] = 0;
for (ll i = 2; i <= _sieve_size; i++)
if (bs[i]) { //if not marked
for (ll j = i * i; j <= _sieve_size; j += i) //check all the multiples
bs[j] = 0; // they are surely not prime :-)
primes.push_back((int)i); // this is prime
} }
call from main() sieve(10000);. You have primes list in vector primes.
Note: As mentioned in comment--stackoverflow is quite unexpected error here. You are implementing sieve but it will be more efficient if you use bistet instead of bool.
Few things like if n=10^8 then sqrt(n)=10^4. And your bool array is p[10000]. So there is a chance of accessing array out of bound.
I agree with the other answers,
saying that you should basically just start over. 
Do you even care why your code doesn’t work?  (You didn’t actually ask.)
I’m not sure that the problem in your code
has been identified accurately yet. 
First of all, I’ll add this comment to help set the context:
// For any int aardvark;
// p[aardvark] = false means that aardvark is composite (i.e., not prime).
// p[aardvark] = true means that aardvark might be prime, or maybe we just don’t know yet.
Now let me draw your attention to this code:
int i=rootn;
while(i--)
{
if(p[i]==true)
{
int c=i;
do
{
c=c+i;
p[c]=false;
}while(c+p[i]<=rootn);
}
};
You say that n≤100000000 (although your code doesn’t check that), so,
presumably, rootn≤10000, which is the dimensionality (size) of p[]. 
The above code is saying that, for every integer i
(no matter whether it’s prime or composite),
2×i, 3×i, 4×i, etc., are, by definition, composite. 
So, for c equal to 2×i, 3×i, 4×i, …,
we set p[c]=false because we know that c is composite.
But look closely at the code. 
It sets c=c+i and says p[c]=false
before checking whether c is still in range
to be a valid index into p[]. 
Now, if n≤25000000, then rootn≤5000. 
If i≤ rootn, then i≤5000, and, as long as c≤5000, then c+i≤10000. 
But, if n>25000000, then rootn>5000,†
and the sequence i=rootn;, c=i;, c=c+i;
can set c to a value greater than 10000. 
And then you use that value to index into p[]. 
That’s probably where the stack overflow occurs.
Oh, BTW; you don’t need to say if(p[i]==true); if(p[i]) is good enough.
To add insult to injury, there’s a second error in the same block:
while(c+p[i]<=rootn). 
c and i are ints,
and p is an array of bools, so p[i] is a bool —
and yet you are adding c + p[i]. 
We know from the if that p[i] is true,
which is numerically equal to 1 —
so your loop termination condition is while (c+1<=rootn);
i.e., while c≤rootn-1. 
I think you meant to say while(c+i<=rootn).
Oh, also, why do you have executable code
immediately after an unconditional return statement? 
The system("PAUSE"); statement cannot possibly be reached.
(I’m not saying that those are the only errors;
they are just what jumped out at me.)
______________
† OK, splitting hairs, n has to be ≥ 25010001
(i.e., 50012) before rootn>5000.

C++ algorithm optimization: find K combination from N elements

I am pretty noobie with C++ and am trying to do some HackerRank challenges as a way to work on that.
Right now I am trying to solve Angry Children problem: https://www.hackerrank.com/challenges/angry-children
Basically, it asks to create a program that given a set of N integer, finds the smallest possible "unfairness" for a K-length subset of that set. Unfairness is defined as the difference between the max and min of a K-length subset.
The way I'm going about it now is to find all K-length subsets and calculate their unfairness, keeping track of the smallest unfairness.
I wrote the following C++ program that seems to the problem correctly:
#include <cmath>
#include <cstdio>
#include <iostream>
using namespace std;
int unfairness = -1;
int N, K, minc, maxc, ufair;
int *candies, *subset;
void check() {
ufair = 0;
minc = subset[0];
maxc = subset[0];
for (int i = 0; i < K; i++) {
minc = min(minc,subset[i]);
maxc = max(maxc, subset[i]);
}
ufair = maxc - minc;
if (ufair < unfairness || unfairness == -1) {
unfairness = ufair;
}
}
void process(int subsetSize, int nextIndex) {
if (subsetSize == K) {
check();
} else {
for (int j = nextIndex; j < N; j++) {
subset[subsetSize] = candies[j];
process(subsetSize + 1, j + 1);
}
}
}
int main() {
cin >> N >> K;
candies = new int[N];
subset = new int[K];
for (int i = 0; i < N; i++)
cin >> candies[i];
process(0, 0);
cout << unfairness << endl;
return 0;
}
The problem is that HackerRank requires the program to come up with a solution within 3 seconds and that my program takes longer than that to find the solution for 12/16 of the test cases. For example, one of the test cases has N = 50 and K = 8; the program takes 8 seconds to find the solution on my machine. What can I do to optimize my algorithm? I am not very experienced with C++.
All you have to do is to sort all the numbers in ascending order and then get minimal a[i + K - 1] - a[i] for all i from 0 to N - K inclusively.
That is true, because in optimal subset all numbers are located successively in sorted array.
One suggestion I'd give is to sort the integer list before selecting subsets. This will dramatically reduce the number of subsets you need to examine. In fact, you don't even need to create subsets, simply look at the elements at index i (starting at 0) and i+k, and the lowest difference for all elements at i and i+k [in valid bounds] is your answer. So now instead of n choose k subsets (factorial runtime I believe) you just have to look at ~n subsets (linear runtime) and sorting (nlogn) becomes your bottleneck in performance.