The problem is to print all subsets that sum up to a value. I wrote code to check if there is a possible subset. Can some one gimme an idea to print the numbers that form the sum. Below is my code. Assume the array contains only +ve nos for simplicity.
void subsetsum(int A[], int target) {
int N = sizeof(A)/sizeof(int), sum = 0;
for(int i = 0; i < N; i++) sum += A[i];
vector<bool> V(sum + 1, 0);
V[0] = 1;
for(int i = 0; i < N; i++)
for(int j = sum; j >= 0; j--) {
if(j + A[i] <= sum && V[j]) V[A[i] + j] = 1;
}
if(V[target]) cout << "Sumbset sum exists" << endl;
else cout << "Sumbset sum doesnt exist" << endl;
}
First you need to generate all the subsets
If [a,b,c,d] is given array, think about generating subsets taking each element from array one at a time.
subsets(X) including y = foreach x in X append y to x
Taking a, we get subsets(a) = { [], [a] }
Take b, we get subsets(a,b) = subsets(a) + (subsets(a) including b)
= { [], [a] } + { [b], [a,b] } = { [], [a], [b], [a,b] }
Take c, subsets(a,b,c) = subsets(a,b) + (subsets(a,b) including c)
= {[], [a],[b],[a,b]} + {[c], [a,c], [b,c], [a,b,c]}
Once you get all subsets, print those whose sums equals target. You can modify the above algo further if you don't need any subsets.
Here's an answer in javascript:
function subsetsum(A, target) {
//int N = sizeof(A)/sizeof(int), sum = 0;
var N = A.length, sum = 0;
//for(int i = 0; i < N; i++) sum += A[i];
for(var i = 0; i < N; i++) sum += A[i];
// vector<bool> V(sum + 1, 0);
var V = [];
V[0] = [];
for(var i = 0; i < N; i++) {
for(var j = sum; j >= 0; j--) {
if(j + A[i] <= sum && V[j]) {
//Join the subset of the memoized result to this result.
V[A[i] + j] = [A[i]].concat(V[j]);
}
}
}
console.log(V);
//evaluates to true if V[target] exists
return !!V[target];
}
function to find power set of a vector<int>
vector<vector<int>> power_set(const vector<int>& nums) {
if (nums.empty()) { return { {} }; }
auto set = power_set(vector<int>(begin(nums) +1, end(nums)));
auto tmp = set;
for (auto& p : tmp) {
p.push_back(nums[0]);
}
set.insert(end(set), begin(tmp), end(tmp));
return set;
}
function that return all sets in the power set that sum to target
vector<vector<int>> test_sum(const vector<vector<int>>& ps, int target) {
vector<vector<int>> v;
for (auto& p : ps) {
int sum = accumulate(begin(p), end(p), 0);
if (sum == target) {
v.push_back(p);
}
}
return v;
}
I modified your code to print the numbers.
void subsetsum(int A[], int target) {
int N = sizeof(A) / sizeof(int), sum = 0;
for (int i = 0; i < N; i++) sum += A[i];
vector<bool> V(sum + 1, 0);
V[0] = 1;
for (int i = 0; i < N; i++)
for (int j = sum; j >= 0; j--) {
if (j + A[i] <= sum && V[j]) V[A[i] + j] = 1;
}
if (V[target]) cout << "Sumbset sum exists" << endl;
else cout << "Sumbset sum doesnt exist" << endl;
if (V[target])
{
for (int i = N - 1; i >= 0; i--)
{
if (V[target - A[i]] == 1) printf("%d, ", A[i]), target -= A[i];
}
printf("\n");
}
}
or Here's my version with vector
bool subsetsum_dp(vector<int>& v, int sum)
{
int n = v.size();
const int MAX_ELEMENT = 100;
const int MAX_ELEMENT_VALUE = 1000;
static int dp[MAX_ELEMENT*MAX_ELEMENT_VALUE + 1]; memset(dp, 0, sizeof(dp));
dp[0] = 1;
for (int i = 0; i < n; i++)
{
for (int j = MAX_ELEMENT*MAX_ELEMENT_VALUE; j >= 0; j--)
{
if (j - v[i] < 0) continue;
if (dp[j - v[i]]) dp[j] = 1;
}
}
if (dp[sum])
{
for (int i = n - 1; i >= 0; i--)
{
if (dp[sum - v[i]] == 1) printf("%d, ", v[i]), sum -= v[i];
}
printf("\n");
}
return dp[sum] ? true : false;
}
Related
#include <bits/stdc++.h>
using namespace std;
int solve(int A, vector<int> &B) {
vector<int> pre(A);
vector<int> suff(A);
vector<int> p;
vector<int> s;
int sum = 0;
int ans = 0;
for (int i = 0; i < A; i++) {
sum = sum + B[i];
}
if (sum % 3 != 0)
return 0;
sum = sum / 3;
for (int i = 0; i < A; i++) {
if (i == 0) {
pre[i] = B[i];
if (pre[i] == sum) {
p.push_back(i);
}
continue;
}
pre[i] = B[i] + pre[i - 1];
if (pre[i] == sum) {
p.push_back(i);
}
}
for (int i = A - 1; i >= 0; i--) {
if (i == A - 1) {
suff[A - 1] = B[A - 1];
if (suff[i] == sum) {
s.push_back(i);
}
continue;
}
suff[i] = B[i] + pre[i + 1];
if (suff[i] == sum) {
s.push_back(i);
}
}
for (int i = 0; i < p.size(); i++) {
for (int j = s.size(); j >= 0; j++) {
if (s[j] > p[i] + 1) {
ans++;
}
}
}
return ans;
}
int main() {
int A = 5;
vector<int> B = {1, 2, 3, 0, 3};
cout << solve(5, B);
return 0;
}
The code keeps getting dumped at pre[i]=B[i]. The code is very simple for counting the number of ways to split all the elements of the array into 3 contiguous parts so that the sum of elements in each part is the same.
I just made a prefix and suffix sum array.
I've read many posts but I can't figure out where is my error so I go with it.
My program throws the segfault at the cout<<endl. When I erase it, the program doesn't even print anything. It just prints the segfault. Aparently the program never reach to sort the vector.
#include <iostream>
#include <vector>
using namesapce std
void inserctionSort(std::vector<double> &v, int i, int j)
{
double temp;
for(i; i < v.size(); i++)
{
temp = v[i];
j = i - 1;
while((v[j] > temp) && (j >= 0))
{
v[j+1] = v[j];
j--;
}
v[j+1] = temp;
}
}
void merge_(std::vector<double> &v, int i, int k, int j)
{
std::vector<double> w(v.size());
int n = j - i + 1;
int p = i;
int q = k + 1;
for(int l = 0; l < n; l++)
{
if(p <= k && (q > j || v[p] <= v[q]))
{
w[l] = v[p];
p++;
}else
{
w[l] = v[q];
q++;
}
}
for(int l = 0; l < n; l++)
v[i - 1 + l] = w[l];
}
void mergeSort(std::vector<double> &v, int i, int j)
{
int n = j - i + 1, n0 = 3;
int k;
if(n <= n0)
{
inserctionSort(v,i,j);
}else
{
k = i - 1 + n / 2;
mergeSort(v, i, k);
mergeSort(v, k + 1, j);
merge_(v, i, k, j);
}
}
int main()
{
vector<double> v1 = {3.2,4.1,55.42,2.24,5.424,667.32,35.54};
cout<<"Vector desordenado: ";
for(int i = 0; i < v1.size(); i++)
cout<<v1[i]<<", ";
cout<<"hola";
cout<<endl;
cout<<"hola";
mergeSort(v1, 0, v1.size()-1); //--> Core generado
//quickSort(v1, 0, v1.size()-1);
cout<<"Vector ordenado: ";
for(int i = 0; i < v1.size(); i++)
cout<<v1[i]<<", ";
return 0;
}
You have problems in your code with vector indices assuming value -1 inside a couple of loops.
I have corrected these mistakes below, a working version of your code:
#include <iostream>
#include <vector>
using namespace std;
void inserctionSort(vector<double> &v, int i, int j)
{
int v_size = v.size();
double temp;
for (; i < v_size; i++) {
temp = v[i];
j = i - 1;
while ( (j >= 0) && (v[j] > temp) ) { // swapped conditions, as when j=-1, v[j]>temp is undefined
v[j+1] = v[j];
j--;
}
v[j+1] = temp;
}
}
void merge_(vector<double> &v, int i, int k, int j)
{
vector<double> w( v.size() );
int n = j - i + 1;
int p = i;
int q = k + 1;
for (int l = 0; l < n; l++) {
if ( p <= k && (q > j || v[p] <= v[q]) ) {
w[l] = v[p];
p++;
} else {
w[l] = v[q];
q++;
}
}
for(int l = 0; l < n; l++)
v[i + l] = w[l]; // deleted -1 from v[i - 1 + l], as it leads to v[-1] for i,l = 0
}
void mergeSort(vector<double> &v, int i, int j)
{
int n = j - i + 1, n0 = 3; // n = v.size()
int k;
if (n <= n0) {
inserctionSort(v,i,j);
} else {
k = i - 1 + n / 2;
mergeSort(v, i, k);
mergeSort(v, k + 1, j);
merge_(v, i, k, j);
}
}
int main()
{
vector<double> v1 = {3.2,4.1,55.42,2.24,5.424,667.32,35.54};
cout<<"Vector desordenado: ";
for (unsigned i = 0; i < v1.size(); i++)
cout<<v1[i]<<", ";
cout << "hola";
cout << endl;
cout << "hola";
mergeSort(v1, 0, v1.size()-1); //--> Core generado
//quickSort(v1, 0, v1.size()-1);
cout<<"Vector ordenado: ";
for (unsigned i = 0; i < v1.size(); i++)
cout << v1[i] << ", ";
return 0;
}
I want to make a function that, depending on the depth of nested loop, does this:
if depth = 1:
for(i = 0; i < max; i++){
pot[a++] = wyb[i];
}
if depth = 2:
for(i = 0; i < max; i++){
for( j = i+1; j < max; j++){
pot[a++] = wyb[i] + wyb[j];
}
}
if depth = 3:
for(i = 0; i < max; i++){
for( j = i+1; j < max; j++){
for( k = j+1; k < max; k++){
pot[a++] = wyb[i] + wyb[j] + wyb[k];
}
}
}
and so on.
So the result would be:
depth = 1
pot[0] = wyb[0]
pot[1] = wyb[1]
...
pot[max-1] = wyb[max-1]
depth = 2, max = 4
pot[0] = wyb[0] + wyb[1]
pot[1] = wyb[0] + wyb[2]
pot[2] = wyb[0] + wyb[3]
pot[3] = wyb[1] + wyb[2]
pot[4] = wyb[1] + wyb[3]
pot[5] = wyb[2] + wyb[3]
I think you get the idea. I can't think of a way to do this neatly.
Could someone present an easy way of using recursion (or maybe not?) to achieve this, keeping in mind that I'm still a beginner in c++, to point me in the right direction?
Thank you for your time.
You may use the std::next_permutation to manage the combinaison:
std::vector<int> compute(const std::vector<int>& v, std::size_t depth)
{
if (depth == 0 || v.size() < depth) {
throw "depth is out of range";
}
std::vector<int> res;
std::vector<int> coeffs(depth, 1);
coeffs.resize(v.size(), 0); // flags is now {1, .., 1, 0, .., 0}
do {
int sum = 0;
for (std::size_t i = 0; i != v.size(); ++i) {
sum += v[i] * coeffs[i];
}
res.push_back(sum);
} while (std::next_permutation(coeffs.rbegin(), coeffs.rend()));
return res;
}
Live example
Simplified recursive version:
int *sums_recursive(int *pot, int *wyb, int max, int depth) {
if (depth == 1) {
while (max--)
*pot++ = *wyb++;
return pot;
}
for (size_t i = 1; i <= max - depth + 1; ++i) {
int *pot2 = sums_recursive(pot, wyb + i, max - i, depth - 1);
for (int *p = pot ; p < pot2; ++p) *p += wyb[i - 1];
pot = pot2;
}
return pot;
}
Iterative version:
void sums(int *pot, int *wyb, int max, int depth) {
int maxi = 1;
int o = 0;
for (int d = 0; d < depth; ++d) { maxi *= max; }
for (int i = 0; i < maxi; ++i) {
int i_div = i;
int idx = -1;
pot[o] = 0;
int d;
for (d = 0; d < depth; ++d) {
int new_idx = i_div % max;
if (new_idx <= idx) break;
pot[o] += wyb[new_idx];
idx = new_idx;
i_div /= max;
}
if (d == depth) o++;
}
}
I have written a solution for the above problem but can someone please suggest an optimized way.
I have traversed through the array for count(2 to n) where count is finding subarrays of size count*count.
int n = 5; //Size of array, you may take a dynamic array as well
int a[5][5] = {{1,2,3,4,5},{2,4,7,-2,1},{4,3,9,9,1},{5,2,6,8,0},{5,4,3,2,1}};
int max = 0;
int **tempStore, size;
for(int count = 2; count < n; count++)
{
for(int i = 0; i <= (n-count); i++)
{
for(int j = 0; j <= (n-count); j++)
{
int **temp = new int*[count];
for(int i = 0; i < count; ++i) {
temp[i] = new int[count];
}
for(int k = 0; k < count; k++)
{
for(int l = 0; l <count; l++)
{
temp[k][l] = a[i+k][j+l];
}
}
//printing fetched array
int sum = 0;
for(int k = 0; k < count; k++)
{
for(int l = 0; l <count; l++)
{
sum += temp[k][l];
cout<<temp[k][l]<<" ";
}cout<<endl;
}cout<<"Sum = "<<sum<<endl;
if(sum > max)
{
max = sum;
size = count;
tempStore = new int*[count];
for(int i = 0; i < count; ++i) {
tempStore[i] = new int[count];
}
//Locking the max sum array
for(int k = 0; k < count; k++)
{
for(int l = 0; l <count; l++)
{
tempStore[k][l] = temp[k][l];
}
}
}
//printing finished
cout<<"------------------\n";
//Clear temp memory
for(int i = 0; i < size; ++i) {
delete[] temp[i];
}
delete[] temp;
}
}
}
cout<<"Max sum is = "<<max<<endl;
for(int k = 0; k < size; k++)
{
for(int l = 0; l <size; l++)
{
cout<<tempStore[k][l]<<" ";
}cout<<endl;
}cout<<"-------------------------";
//Clear tempStore memory
for(int i = 0; i < size; ++i) {
delete[] tempStore[i];
}
delete[] tempStore;
Example:
1 2 3 4 5
2 4 7 -2 1
4 3 9 9 1
5 2 6 8 0
5 4 3 2 1
Output:
Max sum is = 71
2 4 7 -2
4 3 9 9
5 2 6 8
5 4 3 2
This is a problem best solved using Dynamic Programming (DP) or memoization.
Assuming n is significantly large, you will find that recalculating the sum of every possible combination of matrix will take too long, therefore if you could reuse previous calculations that would make everything much faster.
The idea is to start with the smaller matrices and calculate sum of the larger one reusing the precalculated value of the smaller ones.
long long *sub_solutions = new long long[n*n*m];
#define at(r,c,i) sub_solutions[((i)*n + (r))*n + (c)]
// Winner:
unsigned int w_row = 0, w_col = 0, w_size = 0;
// Fill first layer:
for ( int row = 0; row < n; row++) {
for (int col = 0; col < n; col++) {
at(r, c, 0) = data[r][c];
if (data[r][c] > data[w_row][w_col]) {
w_row = r;
w_col = c;
}
}
}
// Fill remaining layers.
for ( int size = 1; size < m; size++) {
for ( int row = 0; row < n-size; row++) {
for (int col = 0; col < n-size; col++) {
long long sum = data[row+size][col+size];
for (int i = 0; i < size; i++) {
sum += data[row+size][col+i];
sum += data[row+i][col+size];
}
sum += at(row, col, size-1); // Reuse previous solution.
at(row, col, size) = sum;
if (sum > at(w_row, w_col, w_size)) { // Could optimize this part if you only need the sum.
w_row = row;
w_col = col;
w_size = size;
}
}
}
}
// The largest sum is of the sub_matrix starting a w_row, w_col, and has dimensions w_size+1.
long long largest = at(w_row, w_col, w_size);
delete [] sub_solutions;
This algorithm has complexity: O(n*n*m*m) or more precisely: 0.5*n*(n-1)*m*(m-1). (Now I haven't tested this so please let me know if there are any bugs.)
Try this one (using naive approach, will be easier to get the idea):
#include <iostream>
#include<vector>
using namespace std;
int main( )
{
int n = 5; //Size of array, you may take a dynamic array as well
int a[5][5] =
{{2,1,8,9,0},{2,4,7,-2,1},{5,4,3,2,1},{3,4,9,9,2},{5,2,6,8,0}};
int sum, partsum;
int i, j, k, m;
sum = -999999; // presume minimum part sum
for (i = 0; i < n; i++) {
partsum = 0;
m = sizeof(a[i])/sizeof(int);
for (j = 0; j < m; j++) {
partsum += a[i][j];
}
if (partsum > sum) {
k = i;
sum = partsum;
}
}
// print subarray having largest sum
m = sizeof(a[k])/sizeof(int); // m needs to be recomputed
for (j = 0; j < m - 1; j++) {
cout << a[k][j] << ", ";
}
cout << a[k][m - 1] <<"\nmax part sum = " << sum << endl;
return 0;
}
With a cumulative sum, you may compute partial sum in constant time
std::vector<std::vector<int>>
compute_cumulative(const std::vector<std::vector<int>>& m)
{
std::vector<std::vector<int>> res(m.size() + 1, std::vector<int>(m.size() + 1));
for (std::size_t i = 0; i != m.size(); ++i) {
for (std::size_t j = 0; j != m.size(); ++j) {
res[i + 1][j + 1] = m[i][j] - res[i][j]
+ res[i + 1][j] + res[i][j + 1];
}
}
return res;
}
int compute_partial_sum(const std::vector<std::vector<int>>& cumulative, std::size_t i, std::size_t j, std::size_t size)
{
return cumulative[i][j] + cumulative[i + size][j + size]
- cumulative[i][j + size] - cumulative[i + size][j];
}
live example
I am trying to create a bucketsort algorithm in C++, but it is not working at all. Every run, it adds many new numbers, often very large, such as in the billions, into the array. Does anyone know why this is? Here is the code - (Note that I am passing in an array of size 100, with random numbers from 0 to ~37000, and that the insertion sort function is fully functional and tested multiple times)
It would be greatly appreciated if someone could point out what's wrong.
void bucketSort(int* n, int k)
{
int c = int(floor(k/10)), s = *n, l = *n;
for(int i = 0; i < k; i++) {
if(s > *(n + i)) s = *(n + i);
else if(l < *(n + i)) l = *(n + i);
}
int bucket[c][k + 1];
for(int i = 0; i < c; i++) {
bucket[i][k] = 0;
}
for(int i = 0; i < k; i++) {
for(int j = 0; j < c; j++) {
if(*(n + i) >= (l - s)*j/c) {
continue;
} else {
bucket[j][bucket[j][k]++] = *(n + i);
break;
}
}
}
for(int i = 0; i < c; i++) {
insertionSort(&bucket[i][0], k);
}
}
This line does not compile. int bucket[c][k + 1];
I think the problem is with you bucket indices. This part here
for(int j = 0; j < c; j++) {
if(*(n + i) >= (l - s)*j/c) {
continue;
} else {
bucket[j][bucket[j][k]++] = *(n + i);
break;
}
}
does not do the equivalent of:
insert n[i] into bucket[ bucketIndexFor( n[i]) ]
First it gets the index off by one. Because of that it also misses the break for the numbers for the last bucket. There is also a small error introduced because the index calculation uses the range [0,l-s] instead of [s,l], which are only the same if s equals 0.
When I write bucketIndex as:
int bucketIndex( int n, int c, int s, int l )
{
for(int j = 1; j <= c; j++) {
if(n > s + (l-s)*j/c) {
continue;
} else {
return j-1;
}
}
return c-1;
}
and rewrite the main part of your algorithm as:
std::vector< std::vector<int> > bucket( c );
for(int i = 0; i < k; i++) {
bucket[ bucketIndex( n[i], c, s, l ) ].push_back( n[i] );
}
I get the items properly inserted into their buckets.