Can someone please explain this code in detail? I've tried debugging it but i can't figure out how it produces the result. I've been searching for a solution for the problem and this is the code that I stumbled upon, it produces accurate solutions and I would like to know how it works. Many thanks.
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <limits.h>
using namespace std;
int BalancedPartition ( int a[] , int n ){
int sum = 0;
for( int i = 0 ; i < n ; i++)
sum += a[i];
int *s = new int[sum+1];
s[0] = 1;
for(int i = 1 ; i < sum+1 ; i++) s[i] = 0;
int diff = INT_MAX , ans;
for(int i = 0 ; i < n ; i++)
{
for(int j = sum ; j >= a[i] ; j--)
{
s[j] = s[j] | s[j-a[i]];
if( s[j] == 1 )
{
if( diff > abs( sum/2 - j) )
{
diff = abs( sum/2 - j );
ans = j;
}
}
}
}
return sum-ans-ans;
}
int main()
{
int n,result, arr[300];
cin >>n;
for(int i = 0; i < n; i++)
{
cin>>arr[i];
}
result = BalancedPartition(arr,n);
cout <<abs(result); // The difference between the sums of the two subsets
return 0;
}
The function BalancedPartition first computes the summation of the elements of the array a and stores it in sum. It then allocates an array s that is indexed by possible subset summation values. It serves as a bookkeeping structure that tracks the progress of the inner for loop. If s[j] is 1, it means the value j has been processed, where the value j represents the summation of some subset of elements in the array a. Initially, only s[0] is set to 1, which corresponds to the sum of no elements (the empty subset). diff is used to compute the subset with the summation closest to one half the value of sum, and this subset summation value is stored in ans. Once ans is correctly computed, the value returned is the difference between the summation of the elements not used in ans and ans itself, that is, (sum - ans) - ans. So, what's left is the double for loop, to see how it correctly arrives at diff and ans.
The outer for loop iterates i through all the indexes of the array a. The inner loop iterates j through all possible subset summation values, starting with sum. However, it only recognizes a subset summation value if the value is derivable from a previously recognized subset sum. That is, for any given iteration of j, s[j] becomes 1 only if s[j - a[i]] is 1. Since initially only the empty subset is recognized, the first iteration only recognizes s[a[0]]. The second iteration recognizes s[a[1]] and s[a[0]+a[1]]. The third iteration recognizes s[a[2]], s[a[0]+a[2]], s[a[1]+a[2]] and s[a[0]+a[1]+a[2]]. If you recognize the pattern, you can formulate an inductive argument for the correctness of the algorithm.
Related
My solution :
#include <bits/stdc++.h>
int main() {
int n;//Size of array
std::cin>>n;
std::vector<long long>vec_int;
int temp = n;
while(n--){
long long k ;
std::cin>>k;
vec_int.push_back(k);
}
n = temp;
int num = 0;
for(int i = 0 ; i < n-1 ; i++){
for(int j = i+1; j<n; j++){
if(i<j && i+j == vec_int[i]+vec_int[j])
num++;
}
}
std::cout<<num;
return 0;
}
I am scanning the array which takes about O(n^2) time. On very large arrays the time limit for the question exceeds the 2s duration. I tried sorting the array but didn't get too far. How can I speed this up? Is it possible to do this in O(n) time complexity.
Consider redefinition of your problem. The expression:
i+j == vec_int[i]+vec_int[j]
is algebraically equivalent to:
vec_int[i] - i == -(vec_int[j] - j)
So define:
a[i] = vec_int[i] - i
And now the question is to count how many times a[i] == -a[j].
This can be tested in O(n). Use unordered_map m to count how many times each negative value is present in a. Then for each positive value a[i] will be paired with m[-a[i]] negative values. Also count number of zeroes in a and compute number of pairs between those.
I have an array of size n of integer values and a given number S.
1<=n<=30
I want to find the total number of sub-sequences such that for each sub-sequences elements sum is less than S.
For example: let n=3 , S=5and array's elements be as {1,2,3}then its total sub-sequences be 7 as-
{1},{2},{3},{1,2},{1,3},{2,3},{1,2,3}
but, required sub sequences is:
{1},{2},{3},{1,2},{1,3},{2,3}
that is {1,2,3}is not taken because its element sum is (1+2+3)=6which is greater than S that is 6>S. Others is taken because, for others sub-sequences elements sum is less than S.
So, total of possible sub-sequences be 6.
So my answer is count, which is6.
I have tried recursive method but its time complexity is 2^n.
Please help us to do it in polynomial time.
You can solve this in reasonable time (probably) using the pseudo-polynomial algorithm for the knapsack problem, if the numbers are restricted to be positive (or, technically, zero, but I'm going to assume positive). It is called pseudo polynomial because it runs in nS time. This looks polynomial. But it is not, because the problem has two complexity parameters: the first is n, and the second is the "size" of S, i.e. the number of digits in S, call it M. So this algorithm is actually n 2^M.
To solve this problem, let's define a two dimensional matrix A. It has n rows and S columns. We will say that A[i][j] is the number of sub-sequences that can be formed using the first i elements and with a maximum sum of at most j. Immediately observe that the bottom-right element of A is the solution, i.e. A[n][S] (yes we are using 1 based indexing).
Now, we want a formula for A[i][j]. Observe that all subsequences using the first i elements either include the ith element, or do not. The number of subsequences that don't is just A[i-1][j]. The number of subsequences that do is just A[i-1][j-v[i]], where v[i] is just the value of the ith element. That's because by including the ith element, we need to keep the remainder of the sum below j-v[i]. So by adding those two numbers, we can combine the subsequences that do and don't include the jth element to get the total number. So this leads us to the following algorithm (note: I use zero based indexing for elements and i, but 1 based for j):
std::vector<int> elements{1,2,3};
int S = 5;
auto N = elements.size();
std::vector<std::vector<int>> A;
A.resize(N);
for (auto& v : A) {
v.resize(S+1); // 1 based indexing for j/S, otherwise too annoying
}
// Number of subsequences using only first element is either 0 or 1
for (int j = 1; j != S+1; ++j) {
A[0][j] = (elements[0] <= j);
}
for (int i = 1; i != N; ++i) {
for (int j = 1; j != S+1; ++j) {
A[i][j] = A[i-1][j]; // sequences that don't use ith element
auto leftover = j - elements[i];
if (leftover >= 0) ++A[i][j]; // sequence with only ith element, if i fits
if (leftover >= 1) { // sequences with i and other elements
A[i][j] += A[i-1][leftover];
}
}
}
Running this program and then outputting A[N-1][S] yields 6 as required. If this program does not run fast enough you can significantly improve performance by using a single vector instead of a vector of vectors (and you can save a bit of space/perf by not wasting a column in order to 1-index, as I did).
Yes. This problem can be solved in pseudo-polynomial time.
Let me redefine the problem statement as "Count the number of subsets that have SUM <= K".
Given below is a solution that works in O(N * K),
where N is the number of elements and K is the target value.
int countSubsets (int set[], int K) {
int dp[N][K];
//1. Iterate through all the elements in the set.
for (int i = 0; i < N; i++) {
dp[i][set[i]] = 1;
if (i == 0) continue;
//2. Include the count of subsets that doesn't include the element set[i]
for (int k = 1; k < K; k++) {
dp[i][k] += dp[i-1][k];
}
//3. Now count subsets that includes element set[i]
for (int k = 0; k < K; k++) {
if (k + set[i] >= K) {
break;
}
dp[i][k+set[i]] += dp[i-1][k];
}
}
//4. Return the sum of the last row of the dp table.
int count = 0;
for (int k = 0; k < K; k++) {
count += dp[N-1][k];
}
// here -1 is to remove the empty subset
return count - 1;
}
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.
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.
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.