Maximum sum from two sorted arrays - c++

You are given two sorted integer arrays, which have some common integers. Any common integer between the two sequences constitute an intersection point.
You can start traversing from any of the array and switch to the other array or continue with the same array at an intersection point.
The objective is to find a path that produces the maximum sum of the data.
Take for example the following two sequences where intersection points are printed in bold:
First = 3 5 7 9 20 25 30 40 55 56 57 60 62
Second = 1 4 7 11 14 25 44 47 55 57 100
In the above example, the largest possible sum is 450 which is the result of adding
3, 5, 7, 9, 20, 25, 44, 47, 55, 56, 57, 60, and 62
I wrote the following code but it is not compiling, please help:
/* M: size of the array a
N: size of the array b
*/
int i,j,sum1,sum2,sum,m_i,n_j = 0;
void printIntersectionElements(int *a,int M, int *b, int N) {
if (M == 0)
return (b);
if (N ==0)
return(a);
while( i < M && j < N ){
sum1 = sum1 +a[i];
sum2 = sum2 + b[j];
if(a[i] == b[j]) { // found a common element.
if(sum1>= sum2){
for(;m_i<= i; m_i++)
cout<< a[m_i];
sum = sum +sum1;
m_i = i+1;
}
else {
for(;n_j<= j; n_j++)
cout<< b[n_j];
sum = sum+sum2;
n_j = j+1;
}
sum1 = sum2 = 0;
}
i++;
j++;
}
}

You are trying to return a result from a function that is declared with a void return type. That's not valid C++, which is why you are getting a compiler error.
There may be other errors, too. Read the error messages: they will tell you exactly what and where the problem is.

This question can be solved in O(m+n).
You can maintain a cumulative sum array for both arrays.
First find the intersection point in O(m+n).
Then check which array has maximum sum between two intersection point.
Add them in a variable.
Here is the code.
#include <iostream>
#include <vector>
#include <cstdio>
using namespace std;
void print(int a[], int x, int y) {
for(int i = x; i <= y; i++) {
printf("%d ", a[i]);
}
}
int main ()
{
int i, j, x, y, n, m;
int a0[100], a1[100], sum1[100], sum0[100];
vector <int> v0, v1;
cout << "Enter the value of n and m:\n";
cin >> n >> m;
scanf("%d", &a0[0]);
sum0[0] = a0[0];
for(i = 1; i < n; i++) {
scanf("%d", &a0[i]);
sum0[i] = a0[i] + sum0[i-1]; //cumulative sum for first array
}
scanf("%d", &a1[0]);
sum1[0] = a1[0];
for(i = 1; i < m; i++) {
scanf("%d", &a1[i]);
sum1[i] += a1[i] + sum1[i-1]; //cumulative sum for second array
}
i = 0;
j = 0;
while(i < n && j < m) { //loop breaks when either one of the array ends
if(a0[i] == a1[j]) { //if there is a intersection
v0.push_back(i); //store index of both the arrays
v1.push_back(j);
i++;
j++;
}
else if(a0[i] > a1[j]) { //else increase the index of array
j++; //containing small number
}
else if(a0[i] < a1[j]) {
i++;
}
}
i = 0;
j = 0;
int sum = 0;
while(i < v0.size()) {
x = v0[i];
y = v1[i];
if(i == 0) {
if(sum0[x] > sum1[y]) { //check which array has greater sum
sum += sum0[x]; //first intersection
print(a0, 0, x);
}
else {
sum += sum1[y];
print(a1, 0, y);
}
i++;
}
else {
if(sum0[x]-sum0[v0[i-1]] > sum1[y]-sum1[v1[i-1]]) {
sum += sum0[x]-sum0[v0[i-1]]; //checks which array has greater sum
print(a0, v0[i-1]+1, x); //between two intersectio
}
else {
sum += sum1[y]-sum1[v1[i-1]];
print(a1, v1[i-1]+1, y);
}
i++;
}
}
if(sum0[n-1]-sum0[x] > sum1[m-1]-sum1[y]) {
sum += sum0[n-1]-sum0[x]; //check which array has greater sum
print(a0, x+1, n-1); //at last intersection
}
else {
sum += sum1[m-1]-sum1[y];
print(a1, y+1, m-1);
}
cout << endl << "sum = " << sum << endl;
return 0;
}

Your code has several problems:
First of it doesn't compile, since your function is declared to return void, but you try to return int*. Change your return statements to return;
However even if you fix that your function doesn't solve the problem you have described.
Your summation stops when you reach the end of the smaller of the two arrays. However from your example you should actually go till the end of both arrays.
Furthermore you only detect intersection points when both arrays contain the same number at the same position, however from your text I would think that you should detect points as intersections, even if they are at different positions in the array (I might be wrong though, depending on the exact formulation of your exercise). To do that the easiest way would be to handle only the smaller value of a[i] and b[j] each iteration (and increase only either i or j (or both if its an intersection).

Related

Trying to make a simple Array sorter with input numbers

I'm very new to C++ or even coding. I was trying to make a simple array sorter, where the I first input the number of elements that will be in the array and then input the elements. My outcome should be the array sorted in ascending order. I have not thought about the case if elements inserted are same. So I would love to get some help from you folks.
The main error that I'm facing is that only the first unsorted element is sorted while the rest are either interchanged or left the same.
int main(){
int x;
cout<<"Enter no. of elements"<<endl;
cin>>x;
int A[x];
for (int i = 0;i<x;i++){
cin>>A[i];
}
for(int i=0;i<x;i++)
cout<<A[i]<<",";
int count=0;
if(count <= (x-1)){
for (int i=0;i<(x-1);i++){
if(A[i]>A[i+1]){
int a;
a = A[i];
A[i] = A[(i+1)];
A[i+1] = a;
}
else if(A[i]<A[i+1])
count++;
}
}
cout<<"Sorted array:";
for(int i=0;i<x;i++)
cout<<A[i]<<",";
return 0;
}
You declared a variable length array
int x;
cout<<"Enter no. of elements"<<endl;
cin>>x;
int A[x];
because its size is not a compile-time constant.
However variable length arrays are not a standard C++ feature though some compilers have their own language extensions that support variable length arrays,
It is better to use the class template std::vector.
Another problem is that it seems you are trying to use the bubble sort method to sort the array. But this method requires two loops.
Here is a demonstration program that shows how the bubble sort algorithm can be implemented.
#include <iostream>
int main()
{
int a[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
const size_t N = sizeof( a ) / sizeof( *a );
for (const auto &item : a)
{
std::cout << item << ' ';
}
std::cout << '\n';
for (size_t last = N, sorted = N; not ( last < 2 ); last = sorted)
{
for (size_t i = sorted = 1; i < last; i++)
{
if (a[i] < a[i - 1])
{
// std::swap( a[i-1], a[i] );
int tmp = a[i - 1];
a[i - 1] = a[i];
a[i] = tmp;
sorted = i;
}
}
}
for (const auto &item : a)
{
std::cout << item << ' ';
}
std::cout << '\n';
}
The program output is
9 8 7 6 5 4 3 2 1 0
0 1 2 3 4 5 6 7 8 9
Let us try the following method:
find the largest element in the array and move it to the end, by swapping with the last element;
repeat with the array but the last element, and so on.
To find the largest element in A[0..m-1], scan the array and keep an index to the largest so far, let l. This index can be initialized to 0.
// Move the largest to the end
int l= 0;
for (int i= 1; i < m; i++)
{
if (A[i] > A[l]) l= i;
}
// A[l] is the largest in A[0..m-1]
Swap(A[l], A[m-1]);
// A[m-1] is the largest in A[0..m-1]
To sort, repeat with decreasing m. You can stop when the subarray just holds one element:
// Sort
for (int m= n-1; m > 1; m--)
{
// Move the largest to the end
....
}
Writing the Swap operation and assembling the whole code is your task. Also check
correctness of the Move for the limit cases m= 0, 1, 2.
correctness of the Sort for the limit cases n= 1, 2, 3.
how you could instrument the code to verify that the Move does its job.
how you could instrument the code to verify that the Sort does its job.
what happens in case of equal keys.
Your code can be fixed a bit to make it working.
Just replace if (count <= (x - 1)) with while (count < (x - 1)) and also set count = 0; at start of loop, plus replace else if (A[i] < A[i + 1]) with just else. And your code becomes working!
Necessary fixes I did in code below. Also I did formatting (indents and spaces) to make code looks nicer. Rest remains same.
As I see you have a kind of Bubble Sort.
Try it online!
#include <iostream>
using namespace std;
int main() {
int x;
cout << "Enter no. of elements" << endl;
cin >> x;
int A[x];
for (int i = 0; i < x; i++) {
cin >> A[i];
}
for (int i = 0; i < x; i++)
cout << A[i] << ",";
int count = 0;
while (count < (x - 1)) {
count = 0;
for (int i = 0; i < (x - 1); i++) {
if (A[i] > A[i + 1]) {
int a;
a = A[i];
A[i] = A[(i + 1)];
A[i + 1] = a;
} else
count++;
}
}
cout << "Sorted array:";
for (int i = 0; i < x; i++)
cout << A[i] << ",";
return 0;
}
Input:
10
7 3 5 9 1 8 6 0 2 4
Output:
7,3,5,9,1,8,6,0,2,4,Sorted array:0,1,2,3,4,5,6,7,8,9,
If you are taking the size of array as input from user you have to create your array dynamically in c++ like
int *array=new int(x)
and after taking the inputs of the elements just run a nested loop from 0 to size and
the inner loop from 0 to size-1 and check if(A[i]>A[i+1]) if true then swap the values else continue

Stuck on recursion algorithm in arrays

I got stuck with the following task:
"Write a recursive function that takes a one-dimensional array of 100 randomly set integers and finds the position at which a sequence of 10 numbers begins with the minimum sum".
I've written 2 functions:
int recursiveArrSum(int mass[], int dim = 10, int sum = 0) {
if (dim == 0) return sum;
sum += mass[dim-1];
return recursiveArrSum(mass, --dim, sum);
}
int recArrMinSum(int mass[], int dim=100, int tempSum=100, int idx=0, int addPar=0){
if (dim == 0) return idx;
mass[dim]=mass[addPar];
if (tempSum >= recursiveArrSum(mass)){
tempSum = recursiveArrSum(mass);
idx = dim-1;
//mass[dim]=mass[addPar];
}return recArrMinSum(mass, --dim, tempSum, idx, ++addPar);
1st one (recursiveArrSum) - works fine, but the second one drives me crazy...
I can't understand how I need to iterate an array during evoking the function on last return statement. I made it using for loop, and it works correctly:
for (int i=0; i<91; i++){
int tempS=0;
for (int j=i; j<=i+9; j++){
tempS += arr[j];
cout << tempS<< endl;
}
if (tempS<tempSum) {
tempSum=tempS;
k=i+1;
}
}
but recursion doesn't...
Could anyone suggest me the way for solving this issue?
Open for any questions.
Thanks in advance.
This is how I would do it:
A function that keeps in its arguments the current position, the current sum, the minimum sum and the starting position of this minimum sum. The function also transports as arguments the array (obviously), its size and the dimension of the sum (10 in your case).
void compute(int mass[], int massSize = 100, int dim = 10, int currentPosition = 0, int currentSum = 0, int minSum = 99999, int minPosition = -1)
{
// Before suming the first dim elements, we keep going adding the element at the current position and we increase the current position.
if (currentPosition < dim)
{
compute(mass, massSize, dim, currentPosition + 1, currentSum + mass[currentPosition], minSum, minPosition);
return;
}
// When reaching the end of the array, we print our best solution.
if (currentPosition > massSize)
{
std::cout << "Min sum of " << dim << " elements is " << minSum << ", starting at position " << minPosition << std::endl;
return;
}
// In all the other cases, we check if the current sum is better than the minimum sum. If yes, we update the minimum sum and its starting position. Then call again the function!
if (currentSum < minSum)
{
minSum = currentSum;
minPosition = currentPosition - dim;
}
compute(mass, massSize, dim, currentPosition + 1, currentSum + mass[currentPosition ] - mass[currentPosition -dim], minSum, minPosition);
}
Calling the function is easy: compute(mass, SIZE, 10); where mass is your array, SIZE is its size and 10 is your dimension.
With a dimension equals to 5 in this array:
8; 8; 4; 10; 9; 9; 6; 3; 3; 5; 3; 8; 3; 7; 9; 10; 10; 5; 6; 4; 1; 4; 1; 5; 2; 8; 6; 1; 7; 9;
Min sum of 5 elements is 13, starting at position 20
When writing a recursive function, the first things to do is to think about the exit case, the init cases (if there are any) and the "classic" case when you're in the middle of your search.
Feel free to ask any question, I added some comments to make it clear enough.
It is unclear how your code is supposed to work. To iterate the array and find the smallest sum you do something like this (pseudo code):
int currentSum = sum of elements 0 till 9
int smallestSum = currentSum
int smallestIndex = 0
for (i = 10; i < 100; ++i) {
currentSum = currentSum - mass[ i -10] + mass[i]
if (currentSum < smallestSum) {
smallestSum = currentSum
smallestIndex = i
}
}
As initial guess it takes the sum of the first 10 elements, ie elements 0 till 9. After that it iterates the array. Sum of elements 1 till 10 is the same as sum of elements 0 till 9 minus first element plus element 10. More general: To get the sum in the next iteration, element at i-10 is subtracted and element at i is added.
Not exactly sure what you're allowed to include from the STL, but there's this solution:
// Or std::pair<int, int*>
struct resultPair {
int first;
int* second;
};
// Or std::accumulate
int sumOf(int* arr, size_t s) {
int sum = 0;
for (size_t i=0; i<s; ++i)
sum += arr[i];
return sum;
}
resultPair minSeqOfN(int* arr, size_t s, size_t N) {
if (s < N) throw; // Or however you want to check pre-conditions
int sum = sumOf(arr, N);
if (s == N) return { sum, arr }; // Base case
auto nextRes = minSeqOfN(arr+1, s-1, N);
if (nextRes.first < sum) return nextRes;
else return resultPair{sum, arr};
}
The function keeps calling itself minus the first element, until the sequence size is equal to the input array size (then there's just 1 possible answer).

Vector Subscript out of Range; Comparing Elements of Vectors

I am currently working on a program that finds prime numbers, I know there are less convoluted ways to find prime numbers but I'm trying to practice comparing elements in vectors (not_prime_numbers & number bank(numbers from 1-100)) and when a value that is a prime number is found it is put into the final prime_number vector.
I am using loops to compare elements inside the vectors. When I ask the program to display the vector not_prime_numbers this is not a problem, nor number bank, however when I ask it to display the prime_number vector I get the error vector subscript out of range. Why are the vector elements in prime numbers I am asking to display out of range however using the same loop method to display the elements of vectors not_prime_numbers & number_bank work. Is it a problem with how I compared the two vectors to put the element into a third vector (prime_numbers)?
#include "pch.h"
#include <iostream>
#include<vector>
int main()
{
float i = 1.0;
unsigned int n = 0;
std::vector<float>not_prime_numbers;
std::vector<float>number_bank;
std::vector<float>prime_numbers;
while (i <= 100.0)
{
for (float j = 1.0;j<(i);++j)
{
float p = i / j;
if (abs(floor(p)) == p&&j!=1.0)
{
not_prime_numbers.push_back(i);
break;
}
}
++i
}
for (float k = 1.0; k <= 100.0; ++k)
{
number_bank.push_back(k);
}
for (unsigned int m = 0; m <= number_bank.size(); ++m)
{
while (n <= not_prime_numbers.size())
{
if (not_prime_numbers[n] == number_bank[m])
{
break;
}
if (n == m)
{
prime_numbers.push_back(number_bank[m]);
}
if (not_prime_numbers[n] != number_bank[m])
{
++n;
}
}
}
std::cout << "All prime numbers between 0 and 100 are as follows:\n";
for (unsigned int j = 0; j <= prime_numbers.size(); ++j)
{
std::cout << prime_numbers[j] << "\n";
}
}
This is not homework, just personal practice. Any help would be greatly appreciated.
in
while (n <= not_prime_numbers.size())
{
if (not_prime_numbers[n] == number_bank[m])
you go after the last element, test must be n < not_prime_numbers.size()
and same error when you print the result :
for (unsigned int j = 0; j <= prime_numbers.size(); ++j)
{
std::cout << prime_numbers[j] << "\n";
}
must be
for (unsigned int j = 0; j < prime_numbers.size(); ++j)
{
std::cout << prime_numbers[j] << "\n";
}
If valgrind is available on your host, use it to find that kind of errors and lot more

Factorial function only returning inputted answer in C++?

I have to create a program which calculates the factorial of any number, the problem is if I input any number above 20 it just returns that number. What in my else if statement could be causing this and is there a better way to solve this? ( this function is called in main and works if num <= 20)
void factorial() {
//User input for number
long long num;
std::cout << "Input any positive integer to find its factorial: ";
std::cin >> num;
unsigned long long numFact = 1;
if (num <= 20) {
while (num > 0) {
numFact = numFact * num;
num = num - 1;
}
std::cout << numFact;
}
else if (num > 20) {
std::vector<int> multFactorial;
//stores num as seperate elements in vector multFactorial
while (num > 0) {
int remain = num % 10;
num = num / 10;
multFactorial.insert(multFactorial.begin(), remain);
}
std::vector<int> answer;
std::vector<int> answerFinal;
//Manually multiplies elements in multFactorial
//Then adds new vectors created by multiplying to get final answer
//Repeats until factorial is solved
//Ex: 21 * 20; 0 * 1 and 0 * 2 stored as {0 , 0}
//2*1 and 2*2 stored as {4, 2, 0}
//Vectors will be addes to get {4, 2, 0} and then that will be multiplied
by 19 until num = 1
while (num > 1) {
for (int i = multFactorial.size() - 1; i >= 0; i--) {
int remain1 = ((num - 1) % 10) * multFactorial[i];
answer.insert(answer.begin(), remain1);
int remain2 = (((num - 1) / 10) * multFactorial[i]);
answerFinal.insert(answerFinal.begin(), remain2);
}
answerFinal.insert(answerFinal.begin(), 0);
//Adds vectors to get final value seperate as digits
for (int i = multFactorial.size() - 1; i >= 0; i--) {
multFactorial[i] = answer[i] + answerFinal[i];
}
num = num - 1;
}
//Prints what should be the factorial of the number input
for (size_t i = 0; i < multFactorial.size(); i++) {
std::cout << multFactorial[i];
}
}
}
Factorials of large numbers results in huge numbers. This can be accommodated in languages like C, C++ etc by putting the results into arbitrary length strings.
Here is an algorithm for that - similar to yours.
https://www.geeksforgeeks.org/factorial-large-number/
Best advice is to check your code against this.
Use a debugger if you have one and step through the code line by line.
If not print out intermediate results and compare with expected.
EDIT: As per review comment, the code at above ref is similar to below- just in case link is broken in future.
// C++ program to compute factorial of big numbers
#include<iostream>
using namespace std;
// Maximum number of digits in output
#define MAX 100 // change to whatever value you need
int multiply(int x, int res[], int res_size);
// Calculate factorial of large number
void factorial(int n)
{
int res[MAX];
// Initialize result
res[0] = 1;
int res_size = 1;
// Apply factorial formula
for (int x=2; x<=n; x++)
res_size = multiply(x, res, res_size);
// print out the result
cout << "Factorial is \n";
for (int i=res_size-1; i>=0; i--)
cout << res[i];
}
// Multiplies x with the number represented by res[].
// res_size is size of res[] or number of digits in the
// number represented by res[].
int multiply(int x, int res[], int res_size)
{
int carry = 0; // Initialize carry
// One by one multiply n with individual digits of res[]
for (int i=0; i<res_size; i++)
{
int prod = res[i] * x + carry;
// Store last digit of 'prod' in res[]
res[i] = prod % 10;
// Put rest in carry
carry = prod/10;
}
// Put carry in res and increase result size
while (carry)
{
res[res_size] = carry%10;
carry = carry/10;
res_size++;
}
return res_size;
}
// Main program
int main()
{
//put code here to read a number
factorial(50); // take 50 for example
return 0;
}

"Summable Numbers" in C++

The divisors of n can make the number between 1 to n. This is called a summable number. An example is 12. 1, 2, 3, 4, 6, 12 can be added together in different ways to make the numbers 1 through 12. Now this code gives me all summable numbers from 1 to an user inputed number but it is also giving me some numbers that are not summable such as 14. I am not sure why that is. Where in the code do I have to make a change?
#include <iostream>
#include <vector>
#include <math.h>
using namespace std;
vector <int> divisors;
vector<int> subsetsResult;
vector<int> subset;
bool isSummableNumber(int num)
{
if ((num > 1) && (num % 2 != 0))
{
return false;
}
for (int i=1; i<=num; i++)
{
if (num%i==0)
{
divisors.push_back(i);
int SIZE_OF_DIVISORS_SET = divisors.size();
double COUNTER_LIMIT = pow(2, SIZE_OF_DIVISORS_SET) - 1;
int TOTAL_NUMBER_OF_BITS = 8;
for (int counter = 1; counter <= COUNTER_LIMIT; counter++)
{
int currentValue = counter;
for (int bitIndex = 0; bitIndex < TOTAL_NUMBER_OF_BITS; bitIndex++)
{
if (currentValue & 000001)
{
subset.push_back(divisors[bitIndex]);
}
currentValue = currentValue >> 1;
}
int sum = 0;
for (std::vector<int>::iterator it = subset.begin() ; it != subset.end(); ++it)
sum += *it;
if (sum >= 1 && sum <= num)
{
subsetsResult.push_back(sum);
}
}
subsetsResult;
int counter = 1;
for (std::vector<int>::iterator it = subsetsResult.begin(); it != subsetsResult.end(); ++it)
{
if (counter != *it)
{
return false;
}
counter += 1;
}
return true;
}
}
}
int main()
{
int num;
cout << "Enter a Positive Integer: " ;
cin >> num;
for (int i=1; i<=num; i++)
{
if (isSummableNumber(i))
cout << i << endl;
}
return 0;
}
I'd calculate the set of all numbers from 0 to n that are the sums of divisors that you found so far. std::vector with a size of n + 1 will do fine. Initially, only element 0 is set. Then if you find another divisor d (in pseudo-code)
for (i = n; i >= d; --i)
if (resultset contains i - d)
add i to the result set.
Finally you check whether the set contains all numbers from 0 to n.
This does not do anything: subsetsResult;
Also, don't you get a compiler warning about paths in your function that do not return a value? There is a missing return false; and the end of the function (and maybe and assertion if that return should never be reached).
Right now you're searching divisor combinations before you've even found all the divisors. That's not a good idea, and it likely is hiding your problem.
Either wait until all divisors are found and then iterate the 2**k sums they produce, or else when each new divisor is found, produce sums from the already-known sums and the new divisor, and skip the bit manipulation. For example:
sums = {0}
N=14, i=1, N%i == 0, sums += i + sums => sums = {0, 1+0}
N=14, i=2, N%i == 0, sums += i + sums => sums = {0, 1, 2+0, 2+1}
N=14, i=3, N%i == 2
...
N=14, i=7, N%i == 0, sums += i + sums => sums = {0, 1, 2, 3, 7+0, 7+1, 7+2, 7+3}
Now since 4 < N and 4 is not a member of sums, exclude 14