C++ Separate Positive and Negative Values From An Array - c++

Beginner in C++ here and learning arrays. The program below is supposed to separate positive and negative numbers in an array. However, it is returning random numbers in both the splitPos and splitNeg functions.
Could someone ever so kindly advice and show me what is incorrect in the functions and what can be done to omit these random digits so that only positive and negative digits are returned respectively by the program for each function/loop? I am obviously not seeing and/or understanding what is incorrect.
Thank you so very much for your help and time in advance!!!
#include <iostream>
using namespace std;
//function prototypes
int splitNeg(int[], int[], int);
int splitPos(int[], int[], int);
void displayArr(int[], int);
int main()
{
const int SIZE = 20;
int usedPos, usedNeg;
int origArr[SIZE] = { 4, -7, 12, 6, 8, -3, 30, 7, -20, -13, 17, 6, 31, -4, 3, 19, 15, -9, 12, -18 };
int posArray[SIZE];
int negArray[SIZE];
usedPos = splitPos(origArr, posArray, SIZE);
usedNeg = splitNeg(origArr, negArray, SIZE);
cout << "Positive Values: " << endl;
displayArr(posArray, usedPos);
cout << endl;
cout << "Negative Values: " << endl;
displayArr(negArray, usedNeg);
return 0;
}
int splitPos(int origArr[], int posArray[], int SIZE)
{
int j = 0;
for (int i = 0; i < SIZE; i++ && j++)
{
if (origArr[i] >= 0)
posArray[j] = origArr[i];
}
return j;
}
int splitNeg(int origArr[], int negArray[], int SIZE)
{
int k = 0;
for (int i = 0; i < SIZE; i++ && k++)
{
if (origArr[i] < 0)
negArray[k] = origArr[i];
}
return k;
}
void displayArr(int newArray[], int used)
{
for (int i = 0; i < used; i++)
cout << newArray[i] << endl;
return;
}

If you change your for-loops a bit:
int splitPos(int origArr[], int posArray[], int SIZE)
{
int j = 0;
for (int i = 0; i < SIZE; i++)
{
if (origArr[i] >= 0)
posArray[j++] = origArr[i];
}
return j;
}
int splitNeg(int origArr[], int negArray[], int SIZE)
{
int k = 0;
for (int i = 0; i < SIZE; i++)
{
if (origArr[i] < 0)
negArray[k++] = origArr[i];
}
return k;
}
you will get the result you desire.
The counter variables of your target arrays only get increased if you find a value that matches the criterion of being less (or greater) than 0.
I honestly do not understand what you tried to achieve with a ... hmmm.. "combined" increase like i++ && j++, this goes into short circuit evaluation.

j and k must be incremented only when the correct value is copied to posArray and negArray, by definition.
If the value is the wrong sign, j and k, obviously, should remain unchanged, since the number of values with the right sign, in the corresponding output array, does not change on this iteration.
This is not what the code is doing. It is incrementing them on every iteration of the loop, except for the one where i is 0.

There is a standard algorithm made just for that. It is named std::partition.
Your code with that algorithm will look like this:
struct SplitPosAndNegResult {
std::vector<int> negatives;
std::vector<int> positives;
};
auto splitPosAndNeg(std::array<int, SIZE> orig) {
// Here `it` is the first element of the second partition (positives)
auto it = std::partition(orig.begin(), orig.end(), [](int i){ return i < 0; });
return SplitPosAndNegResult{
std::vector<int>(orig.begin(), it), // negative numbers
std::vector<int>(it, orig.end()) // positive numbers
};
}
Then, use it like that:
int main () {
auto result = splitPosAndNeg({ 4, -7, 12, 6, 8, -3, 30, 7, -20, -13,
17, 6, 31, -4, 3, 19, 15, -9, 12, -18});
for (int n : result.positives) {
std::cout << n << ' ';
}
std::cout << std::endl;
for (int n : result.negatives) {
std::cout << n << ' ';
}
std::cout << std::endl;
}
This program will output this:
7 30 8 17 6 31 6 3 19 15 12 12 4
-18 -7 -9 -4 -13 -3 -20
Here's a live example at Coliru.

All the answers in this post are good, but I'm disappointed that none of them talk about the STL algorithms!
A good c++ programmer must know the language but he have to know also the C++ library.
look the following code:
#include <iostream>
#include <array>
#include <algorithm>
#include <string>
using namespace std;
template<typename T>
void print(const string& desc, T first, T last)
{
cout << desc;
for_each(first, last,
[](const auto& i ) { cout << i << ' ';});
cout << endl;
}
int main()
{
array<int, 20> originalArray = { 4, -7, 12, 6, 8, -3, 30, 7, -20, -13, 17, 6, 31, -4, 3, 19, 15, -9, 12, -18 };
print("original array is ", begin(originalArray), end(originalArray));
auto it = partition(begin(originalArray), end(originalArray),
[](int n) { return n >= 0; });
print("now original array is ", begin(originalArray), end(originalArray));
print("positives are: ", begin(originalArray), it);
print("negatives are: ", it, end(originalArray));
return 0;
}
More generally you want partition your set with a predicate.
Look to my code do you find any if or for? It's impossible make mistakes this way!
The only thing that does matter in the whole code is auto it = partition(begin(originalArray), end(originalArray), [](int n) { return n >= 0; }); that can be read as: partition from start to finish of originalArray elements that are positive.

#include<iostream>
using namespace std;
int main(){
int a[10]={9,4,-3,-2,1,-1,5,7,-9,-5};
int low=0;
int high=10-1;
while(low<high){
while(a[low]>=0){
low++;
}
while(a[high]<=0){
high--;
}
if(low<high){
int temp=a[low];
a[low]=a[high];
a[high]=temp;
}
}
for(int i=0;i<10;i++){
cout<<a[i]<<" ";
}
}
Time Complexity: O(n)

Related

Insert an element in a descending sorted array and keep array sorted

Assuming we have a sorted descending vector, like:
vector<int> array {26,  21,  13,  11,  8,  3,  2}.
I would like to insert a new and different element to the ones already present, so that descending sort of vector is kept.
Example flow:
I want to insert element 22, basically added at index 1, thus vector would be: 26, 22, 21, 13, 11, 8, 3, 2
I want to insert element 17, basically added at index 3, thus vector would be: 26, 22, 21, 17, 13, 11, 8, 3, 2
I want to insert element 1, basically added at a new index, thus vector would be: 26, 22, 21, 17, 13, 11, 8, 3, 2, 1
I want to insert element 43, basically added at index 0, thus vector would be: 43, 26, 22, 21,  17, 13, 11, 8, 3, 2, 1
A fast sample implementation in C++ would be:
#include<iostream>
#include<vector>
#include <chrono>
using namespace std;
using namespace std::chrono;
int get_Index_Insert(const vector<int>& array, int lengthArray, int insertValue)
{
int whereInsert = lengthArray;
for (int i = 0; i < lengthArray; i++)
{
if (array[i] < insertValue)
{
whereInsert = i;
break;
}
}
return whereInsert;
}
int get_Index_Insert2(const vector<int>& array, int lengthArray, int insertValue)
{
int whereInsert = lengthArray;
// Break out early if these cases:
if (lengthArray == 0 || (array[lengthArray - 1] > insertValue))
return whereInsert;
// Otherwise do your binary magic:
int low = 0;
int high = lengthArray - 1;
while (low <= high)
{
int mid = low + (high - low) / 2;
if (array[mid] > insertValue)
{
low = mid + 1;
}
else
{
high = mid - 1;
}
}
whereInsert = high + 1;
return whereInsert;
}
vector<int> insert_Value(const vector<int>& arrayInput, int insertValue)
{
vector<int> arrayOutput;
int lenghtArray = arrayInput.size();
// At what index to add?
int whereInsert = get_Index_Insert(arrayInput, lenghtArray, insertValue);
// Add it now:
for (int i = 0; i < whereInsert; i++)
arrayOutput.push_back(arrayInput[i]);
arrayOutput.push_back(insertValue);
for (int i = whereInsert + 1; i < lenghtArray + 1; i++)
arrayOutput.push_back(arrayInput[i - 1]);
return arrayOutput;
}
vector<int> insert_Value2(const vector<int>& arrayInput, int insertValue)
{
vector<int> arrayOutput;
int lenghtArray = arrayInput.size();
// At what index to add?
int whereInsert = get_Index_Insert2(arrayInput, lenghtArray, insertValue);
// Add it now:
for (int i = 0; i < whereInsert; i++)
arrayOutput.push_back(arrayInput[i]);
arrayOutput.push_back(insertValue);
for (int i = whereInsert + 1; i < lenghtArray + 1; i++)
arrayOutput.push_back(arrayInput[i - 1]);
return arrayOutput;
}
int main()
{
{
// START TIME
auto start = high_resolution_clock::now();
vector<int> array{ 26, 21, 13, 11, 8, 3, 2 };
array = insert_Value(array, 22);
array = insert_Value(array, 17);
array = insert_Value(array, 1);
array = insert_Value(array, 43);
auto stop = high_resolution_clock::now();
// END TIME
// Show time:
auto duration = duration_cast<microseconds>(stop - start);
cout << "Time taken by function 1, linear search: " << duration.count() << " microseconds" << endl;
for (int i = 0; i < array.size(); i++)
cout << array[i] << " ";
cout << endl;
}
{
// START TIME
auto start = high_resolution_clock::now();
vector<int> array{ 26, 21, 13, 11, 8, 3, 2 };
array = insert_Value2(array, 22);
array = insert_Value2(array, 17);
array = insert_Value2(array, 1);
array = insert_Value2(array, 43);
auto stop = high_resolution_clock::now();
// END TIME
// Show time:
auto duration = duration_cast<microseconds>(stop - start);
cout << "Time taken by function 2, binary search: " << duration.count() << " microseconds" << endl;
for (int i = 0; i < array.size(); i++)
cout << array[i] << " ";
cout << endl;
}
cout << endl << endl << endl;
return 0;
}
Other info that may help in deciding recommended method:
I cannot use anything else than class vector from STL; (only using it as a holder + it's push_back function, nothing else as helper function from it);
I will not have more than a 1000 elements ever in the vector.
Is there any way better to do it than above? in less complexity involved? Any source material I may have missed and that might help is very much appreciated also.
EDIT:
After some more investigations and using binary search method while seeking index position for actual element insertion (thanks to the debates from comments), edited my above sample a bit, testing execution time of a "get_Index_Insert2(...) function using early returns and binary search.
Times received (microseconds), after 3 runs:
Time taken by function 1, linear search: 60 microseconds
43 26 22 21 17 13 11 8 3 2 1
Time taken by function 2, binary search: 33 microseconds
43 26 22 21 17 13 11 8 3 2 1
Time taken by function 1, linear search: 61 microseconds
43 26 22 21 17 13 11 8 3 2 1
Time taken by function 2, binary search: 34 microseconds
43 26 22 21 17 13 11 8 3 2 1
Time taken by function 1, linear search: 61 microseconds
43 26 22 21 17 13 11 8 3 2 1
Time taken by function 2, binary search: 34 microseconds
43 26 22 21 17 13 11 8 3 2 1
Instead of creating a new vector you can use the insert function to put the new value into the existing list at the desired index. See https://en.cppreference.com/w/cpp/container/vector/insert
void insert_Value(const vector<int>& arrayInput, int insertValue)
{
int lenghtArray = arrayInput.size();
// At what index to add?
int whereInsert = get_Index_Insert(arrayInput, lenghtArray, insertValue);
arrayInput.insert(whereInsert, insertValue);
}
#include <algorithm>
#include<iostream>
#include<vector>
using namespace std;
std::vector<int>::const_iterator get_Index_Insert(const vector<int>& array ,int insertValue) {
return std::find_if(array.cbegin(),array.cend(),[insertValue](int aValue) { return aValue < insertValue;});
}
void insert_Value(vector<int>& arrayInput, int insertValue, std::vector<int>::const_iterator aIt)
{
arrayInput.insert(aIt,insertValue);
}
int main()
{
vector<int> array{26, 21, 13, 11, 8, 3, 2 };
auto myIt = get_Index_Insert(array,22);
insert_Value(array,22,myIt);
for (int i = 0; i < array.size(); i++)
cout << array[i] << " ";
cout << endl << endl << endl;
return 0;
}
This is only an idea, then it can be enhanced
You don't need to pass the size of the vector, std::vector already have a member function size().
I think you overcomplicated things. You just have to iterate over the vector and compare each element with the value you want to insert. If the comparison evaluates to false, then you found where to insert the new element.
You may implement the function the following way:
template <typename val_t, typename Compare>
void insert_ordered(std::vector<val_t> & vec, const val_t & val, Compare comp)
{
bool inserted(false);
for(typename std::vector<val_t>::iterator it = vec.begin(); !inserted && (it != vec.end()); ++it)
{
if(!comp(*it, val))
{
vec.insert(it, val);
inserted = true;
}
}
if(!inserted)
vec.push_back(val);
}
It takes the vector, the value to instert and the comparison function you want.
For your use case, it may be used like this:
int main()
{
std::vector<int> v {26, 21, 13, 11, 8, 3, 2};
insert_ordered(v, 22, std::greater<int>());
insert_ordered(v, 17, std::greater<int>());
insert_ordered(v, 1, std::greater<int>());
insert_ordered(v, 43, std::greater<int>());
for(const int & i : v)
std::cout << i << ' ';
return 0;
}
Output:
43 26 22 21 17 13 11 8 3 2 1
Live example
If, for some reason, you can't use std::greater, you can define your own comparator like this:
auto desc_comp = [](const int & lhs, const int & rhs)
{
return lhs > rhs;
};
And use it like this:
insert_ordered(v, 22, desc_comp);
Edit:
If you don't mind having several exit points in the function, it can be simplified as:
template <typename val_t, typename Compare>
void insert_ordered(std::vector<val_t> & vec, const val_t & val, Compare comp)
{
for(typename std::vector<val_t>::iterator it = vec.begin(); it != vec.end(); ++it)
{
if(!comp(*it, val))
{
vec.insert(it, val);
return;
}
}
vec.push_back(val);
}

How to print Even Number after 4 Odd Number with C++

I use this script to print odd number from 1 to 30.
#include <iostream>
using namespace std;
int main( ) {
int i = 1 ;
// whele loop from 1 to 30
while (i <= 30) {
cout << i<< " , ";
i = i + 2;
}
return 0;
}
So the output Will be 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29
What i must to do if i want to add Even number after 4 Odd numbers. The output Will be like 1, 3, 5, 7, 10, 11, 13, 15, 17, 20, 21, 23, 25, 27, 30.
I hope someone can help me with this problem. Thank you
At each iteration you print a number as you are doing now, however, every 5th iterations what you do is a bit different. This is a condition you need to test in each iteration: if true, print like this, if false, print like that.
Start with the loop as you did. Since you using a counting variable that you always increment, a for loop seems more natural than a while.
int main() {
for(int i = 1; i <= 30; i += 2) {
cout << i << " , ";
}
return 0;
}
Now you add the condition test. For that, you can introduce another variable (numOddNumbers) to keep track of how many odd numbers you have printed.
int main() {
int numOddNumbers = 0;
for(int i = 1; i <= 30; i += 2) {
if(numOddNumbers > 0 && numOddNumbers % 4 == 0) {
cout << i + 1 << " , ";
numOddNumbers = 0;
} else {
cout << i << " , ";
numOddNumbers++;
}
}
return 0;
}
For the condition we can use numOddNumbers % 4 == 0 to check that numOddNumbers is amultiple of 4, but since we do not want the condition to be true when numOddNumbers == 0 we also make sure that numOddNumbers > 0.
Notice that differently from i, the numOddNumbers variable is only incremented when the condition is false, since that is when we print an odd number.
This code will print
1 , 3 , 5 , 7 , 10 , 11 , 13 , 15 , 17 , 20 , 21 , 23 , 25 , 27 , 30 ,
Note: An interesting exercise for you is to simplify this code to use just the counting variable, without the extra numOddNumbers variables. The pattern is well defined and you know that the difference is in every 5th itertion.
I can offer the solution of your problem.
#include <iostream>
#include <vector>
using namespace std;
void showContentVector(vector<int>& input)
{
for(int i=0; i<input.size(); ++i)
{
cout<<input[i]<<", ";
}
return;
}
void oddEvenNumbers(int start, int stop, int quantity, vector<int>& input)
{
if(start>stop)
{
return;
}
if(start%2!=0)
{
input.push_back(start);
++quantity;
}
if(quantity==4)
{
start+=3;
input.push_back(start);
quantity=0;
}
oddEvenNumbers(start+1, stop, quantity, input);
return;
}
void solve()
{
vector<int> inputVector;
oddEvenNumbers(0, 30, 0, inputVector);
cout<<"inputVector <- ";
showContentVector(inputVector);
return;
}
int main()
{
solve();
return 0;
}
Here is the result:
inputVector <- 1, 3, 5, 7, 10, 11, 13, 15, 17, 20, 21, 23, 25, 27, 30,
If you will need an explanation of the solution, write the corresponding comment.
#include <iostream>
using namespace std;
int main(void) {
int i = 1;
int step = 1;
while (i <= 30) {
if (step % 5 == 0) {
cout << (i + 1) << ",";
}else{
cout << i << ",";
}
i += 2;
step++;
}
return 0;
}

How do I recursively enumerate all subsets adding to a given sum?

When I try to get the output, it shows same solutions with same element for few times before moving on to another one.
I want to get different solutions from the array that is equal to sum
For instance,
Solution 1 = 14, 8
Solution 2 = 14, 5, 3
Solution 3 = 13, 9
and so on but what I get is repeated solutions for the sum of 22. Im getting this error
Solution : { 14, 8 }
Solution : { 14, 8 }
Solution : { 14, 8 }
Solution : { 14, 8 }
Solution : { 14, 8 }
Solution : { 14, 8 }
Solution : { 14, 5, 3 }
Solution : { 13, 6, 3 }
Solution : { 13, 5, 4 }
Solution : { 13, 5, 4 }
Solution : { 13, 6, 3 }
Solution : { 13, 5, 4 }
Solution : { 13, 5, 4 }
and another 20 lines of the same output.
#include <iostream>
#include <cstdlib>
#include <iomanip>
#include <vector>
#include <algorithm>
using namespace std;
void printSolution(int* r, int k)
{
cout << " Solution : { ";
for (int j = 0; j < k; j++)
{
cout << r[j];
if (j < k - 1)
cout << ", ";
}
cout << " }" << endl;
}
bool subSetSum(int* a, int n, int i, int sum, int* r, int k)
{
if (sum == 0)
printSolution(r, k);
if (i > n)
return false;
r[k++] = a[i];
if (subSetSum(a, n, i + 1, sum - a[i], r, k))
return true;
k -= 1;
subSetSum(a, n, i + 1, sum, r, k);
}
int descendingOrder(const void* a, const void* b)
{
int* p1 = (int*)a;
int* p2 = (int*)b;
return *p2 - *p1;
}
int main()
{
int a[] = { 4, 10, 7, 12, 6, 10, 10, 8, 5, 13, 13, 11, 3, 14 };
int n = 14;
int* r = new int[n];
int k = 0;
qsort(a, n, sizeof(int), descendingOrder);
cout << " Array a[] = ";
for (int count = 0; count < n; count++)
{
cout << a[count] << " ";
}
cout << endl << endl;
int sum = 22;
bool solFound = subSetSum(a, n, 0, sum, r, k);
return 0;
}
You have several errors in your subsetSum function. First of all, your version has a branch where it doesn't return a value. This could have been easily mitigated by enabling compiler warnings.
Second, you have an off-by-one error in your termination condition. i==n is an invalid index, so you will run-over your buffer end.
The reason you get the same result several times is because there are multiple paths to the same result. This is most likely related to the missing return statement.
The fix for this is to terminate the recursion descend once you find a match (when you print it). It is guaranteed that you will not find additional results (unless there are entries <= 0 in your input).
bool subSetSum(int* a, int n, int i, int sum, int* r, int k)
{
if (sum == 0) {
printSolution(r, k);
return true;
}
if (i >= n)
return false;
r[k] = a[i];
bool found = subSetSum(a, n, i + 1, sum - a[i], r, k + 1);
found = subSetSum(a, n, i + 1, sum, r, k) || found;
return found;
}
Please note that this still finds duplicate solutions for duplicate values in your input array (such as 10). You can easily add a check to skip duplicate values in the second recursion call to subSetSum by not passing i + 1 but by finding the next index that is not duplicate. Since you already sorted your input, this can be done by incrementing i until it points to a different value.
Also it should be pointed out that this is quite unidiomatic C++. A better interface to your subsetSum would look like this:
template <typename T, typename ConstIterator>
bool subSetSum(ConstIterator begin, ConstIterator end, T sum, std::vector<T>& buf);
template <typename T, typename ConstIterator>
bool subSetSum(ConstIterator begin, ConstIterator end, T sum) {
std::vector<T> buf;
return subSetSum(begin,end,std::move(T),buf);
}
First of all, no effeciency can be applied here (probably), since this question is NP complete, which means it is probably not solvable in polynomial time.
About the solution, I'll attach a code:
using SolutionT = std::vector<std::set<std::size_t>>;
SolutionT subsetSum(const std::vector<int>& array, int requiredSum, std::size_t index, int currentSum)
{
if (currentSum > requiredSum) { // Remove it if negative integers are present
return {};
}
if (index >= array.size()) {
return {};
}
if (requiredSum == currentSum + array[index]) {
std::set<std::size_t> indices{};
indices.insert(index);
SolutionT solution;
solution.emplace_back(std::move(indices));
return solution;
}
auto includedSolutions = subsetSum(array, requiredSum, index + 1, currentSum + array[index]);
for (auto& solution : includedSolutions) {
solution.insert(index);
}
auto excludedSolutions = subsetSum(array, requiredSum, index + 1, currentSum);
std::copy(std::make_move_iterator(includedSolutions.begin()),
std::make_move_iterator(includedSolutions.end()),
std::back_inserter(excludedSolutions));
return excludedSolutions;
}
SolutionT subsetSum(const std::vector<int>& array, int requiredSum)
{
return subsetSum(array, requiredSum, 0, 0);
}
The code is rather complicated since you need an exponential number of elements, so it is very hard to do without C++ containers.

What's wrong with my solution to Project Euler's #2 in C++?

This is the question:
Each new term in the Fibonacci sequence is generated by adding the
previous two terms. By starting with 1 and 2, the first 10 terms will
be: 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ... By considering the terms in
the Fibonacci sequence whose values do not exceed four million, find
the sum of the even-valued terms.
When I run the program below it gives me
-1833689714
Can someone kindly help me out with the code?
========================================================================
#include <iostream>
using namespace std;
int fibona (int k);
int first = 0 , second = 1 , fibo = 0, sum = 0;
int main()
{
cout << "Sum of even values less than 4000000 : " ;
fibona (4000000);
}
int fibona (int k)
{
for (int c = 0 ; c < k ; c++)
{
if (c <= 1)
{
fibo = c;
}
else
{
fibo = first + second;
first = second;
second = fibo;
}
if (fibo % 2 == 0)
{
sum += fibo;
}
}
cout << sum <<endl;
}
Do you know how much is Fib(4000000)?
Must be approximately
((1+Sqrt[5])/2)^4000000/Sqrt[5] = 1.627477... × 10^835950
There is no way to fit it in any variable type.
#include <iostream>
using namespace std;
long fibona_even_sum (long k);
int main()
{
const long N=4000000;
cout << "Sum of even Fibonacci numbers: " <<endl;
cout << fibona_even_sum(N) <<endl;
}
long fibona_even_sum(long N_max)
{
long first = 0 , second = 1;
long sum=0;
while(true)
{
long first_copy=first;
first=second;
second+=first_copy;
if(second>N_max)
return sum;
if(!(second%2))
sum+=second;
}
}
In the code above you can change all long to int. It works fine.

Solving Subset algorithm using a recursive way gives wrong answer

I have tried to solve the following problem but I still get wrong answer, however the two test cases in the problem are correct answer for me.
Problem Statement: Subsets Sum, or "SS" (double S) for shortcut, is a classical problem in computer science.
We are given a set of positive integer numbers; we have to know if there is a non-empty subset of this set that the sum of its elements is equal to a given number.
Ex: suppose the set is [3, 4, 7, 9, 10] and the target number is 20 The sum of elements of the subset [3, 7, 10] is equal to 20.
Input Format: The input consists of many test cases, each test case is composed of two lines. On the first line of the input file there is a number indicates the number of test cases. The first line of each test case has two integer numbers (k, n): k is the target number, n <= 10 is the number of elements of the set. On the second line there are n integer numbers, each of these numbers is less than one hundred.
Output Format: for each test case print "YES" without quotes if there is a subset that satisfies the condition above, "NO" otherwise.
Sample Input:
2
1 5
45 26 36 4 8
49 8
49 9 5 37 0 42 15 19
Sample Output:
NO
YES
You can test the submission here: http://www.a2oj.com/p.jsp?ID=151
My Code:
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <numeric>
#include <sstream>
#include <iostream>
#include <algorithm>
using namespace std;
bool check = false;
void get(vector<int> arr, long total, int i, int k)
{
int length = arr.size() - 1;
if (i == length*length || i == length)
return;
if (total == k)
{
check = true;
return;
}
if (total >= k && i <= 1)
{
check = false;
return;
}
get(arr, total + arr[i], i + 1, k);
get(arr, total, i + 1, k);
}
int main(void) {
int t;
cin >> t;
vector<int> arr;
while (t--)
{
arr.clear();
int n, k;
cin >> n >> k;
for (int i = 0; i < k; i++)
{
int n;
cin >> n;
arr.push_back(n);
}
get(arr, 0, 0, n);
// arr = { 49,9,5,37,0,42,15,19 };
// get(arr, 0, 0, 49);
if (check)
cout << "YES" << endl;
else
cout << "NO" << endl;
check = false;
}
return 0;
}
I would do that way:
bool SS(const std::vector<int>& v, int total)
{
std::set<int> sums;
for (auto e : v) {
std::set<int> r = sums;
r.insert(e);
for (auto s : sums) {
r.insert(s + e);
}
sums.swap(r);
}
return sums.count(total);
}
where the std::set sums content is all the possible sums from the given vector.
Live example
In the last line of your get function, you are overwriting the value computed by the previous recursive call.
get(arr, total + arr[i], i + 1, k);
get(arr, total, i + 1, k);
So if the first call sets check to true and the second one sets it to false, you will lose first one. This is one of the reasons using global variables is considered harmful, specially in recursive functions.
Instead of defining a global variable, you should change your get function to return a boolean value, and then you can have your recursive like this:
return get(arr, total + arr[i], i + 1, k) || get(arr, total, i + 1, k);
Also try to use more meaningful variable/function names. For example your recursive function can have the following prototype:
bool addsUp(vector<int> array, int total, int from, int length);
As for your k and n variables in the main function, I think you should swap their names to comply with the problem statement (k is the desired total, n is the count of numbers).
And finally your boundary conditions seem to be not quite right. This is the recursive function that got accepted for me:
bool addsUp(vector<int> arr, long soFar, int from, int total) {
if (total == 0)
return false;
if (soFar == total)
return true;
if (soFar > total)
return false;
if (from >= arr.size())
return false;
return addsUp(arr, soFar + arr[from], from + 1, total) || addsUp(arr, soFar, from + 1, total);
}
I have a recursive code which you could have a try,
#include <iostream>
#include <vector>
bool find_subset(const std::vector<int>& input_data, int N, int target_value)
{
if (N == 1)
return input_data[0] == target_value;
bool result = false;
for (int i = 0; i < N; ++i)
{
std::vector<int> copy = input_data;
copy.erase(copy.begin() + i);
if (input_data[i] == target_value || find_subset(copy, N - 1, target_value - input_data[i]))
{
result = true;
break;
}
}
return result;
}
int main()
{
std::vector<int> test_1{45, 26, 36, 4, 8}; int target_1 = 1;
std::vector<int> test_2{49, 9, 5, 37, 0, 42, 15, 19}; int target_2 = 49;
std::vector<int> test_3{ 1, 3, 5, 7 }; int target_3 = 13;
std::vector<int> test_4{ 1, 3, 5, 7 }; int target_4 = 14;
std::cout << (find_subset(test_1, test_1.size(), target_1) ? "Yes" : "No") << std::endl;
std::cout << (find_subset(test_2, test_2.size(), target_2) ? "Yes" : "No") << std::endl;
std::cout << (find_subset(test_3, test_3.size(), target_3) ? "Yes" : "No") << std::endl;
std::cout << (find_subset(test_4, test_4.size(), target_4) ? "Yes" : "No") << std::endl;
return 0;
}
The output are:
No
Yes
Yes
No