Reputation: 37
I need to identify the position of a variable from an integer array who has the following properties:
the sum of elements before this variable is equal with the sum of elements after this variable
if the variable doesn't exist, i will show a message.
For example, if x = {1,2,4,2,1}
, the result is 4
with position 2
, because 1 + 2 == 2 + 1
.
Any suggestions? In this example it's easy
if((x[0]+x[1])==(x[3]+x[4]))
print position 2
But for n
variables?
Upvotes: 1
Views: 241
Reputation: 45654
Well, do it in two steps:
Use standard algorithms and range-for, and it's easily written:
auto first_balanced(std::span<const int> x) noexcept {
auto balance = std::accumulate(begin(x), end(x), 0LL);
for (auto&& n : x) {
if (balance == n)
return &n;
balance -= 2 * n;
}
return end(x);
}
Upvotes: 1
Reputation: 16089
Trying to build a solution out of std::algorithm, n+lg n instead of n+~n/2
Warning untested code.
bool HasHalfSum(int& atIndex, const std::vector<int>& v) {
std::vector<int> sum;
sum.reserve(v.size);
std::partial_sum(v.begin(), v.end(), std::back_iterator(sum));
// 1,3,7,9,10
int half = sum.back() / 2; // 5
auto found = std::lower_bound(sum.begin(), sum.end(), half);
if (found != sum.begin() && std::prev(found) == sum.back() - *found) {
index = std::distance(sum.begin(), found);
return true;
}
return false;
}
Upvotes: 0
Reputation: 32722
Here is the O(n) solution.
Keep summing in in one variable from array beginning(left_sum
) and keep deducing from the sum of elements except the first one using another(right_sum
). When both becomes equal break the loop and print. Otherwise, show your msg.
#include <iostream>
#include <vector>
#include <numeric>
#include <cstddef>
int main()
{
std::vector<int> vec {1,2,4,2,1};
int left_sum = 0;
int right_sum = std::accumulate(vec.cbegin()+1, vec.cend(), 0);
bool Okay = false;
std::size_t index = 1; // start from index 1 until n-1
for( ; index < vec.size() - 1; ++index)
{
left_sum += vec[index-1];
right_sum -= vec[index];
if(left_sum == right_sum)
{
Okay = true;
break;
}
// in the case of array of positive integers
// if(left_sum > right_sum) break;
}
(Okay) ? std::cout << vec[index] << " " << index << std::endl: std::cout << "No such case!\n";
return 0;
}
Upvotes: 2
Reputation: 11406
There are several ways to do this:
Brute force - n/2 passes:
This is not really efficient for larger arrays.
1.5 passes:
half_sum
).half_sum
.Single pass (positive numbers only):
sum1
) and one from the end (sum2
).sum1 = first element
and sum2 = last element
.For each method you'll have to do a litlle check first to see if the array is not too small.
Special cases to consider:
Upvotes: 3
Reputation: 37
Thanks for answers. I finally managed it. I used 3 for loops, and s0 is for sum before the element, and s1 is the sum after the element.
for(i=0;i<n;i++)
{s1=0;
s0=0;
for(int j=0;j<i-1;j++)
s0=s0+v[j];
for(int k=i;k<n;k++)
s1=s1+v[k];
if(s0==s1)
{cout<<endl<<"Position i="<<i;
x++;}
}
if(x==0)
cout<<"doesnt exist";
Upvotes: 1
Reputation: 4313
It's just looping. You need to sum the elements before and after each index and just compare these two sums:
#include <iostream>
#include <vector>
#include <numeric>
int main() {
std::vector<int> x = {1, 2, 4, 2, 1};
for ( unsigned idx = 0; idx < x.size(); ++idx )
if ( std::accumulate(x.begin(), x.begin() + idx, 0) == std::accumulate(x.begin() + idx + 1, x.end(), 0) )
std::cout << idx << std::endl;
return 0;
}
Upvotes: 0