C++: Dynamic programming, given 3 possible operations - c++

Question:
So the question goes like this: I have N numbers. For each number X in the array of length N, I can perform 3 operations: 1. If X is a multiple of 2, divide X by 2. 2. If X is a multiple of 3, divide it by 3. 3. Subtract 1 from X. Find the minimum number of operations to make X = 0. This code is meant to be done using dynamic programming...
Input:
line 1: N line 2: Array X of N numbers
Output:
line 1: Number of operations to reduce X1 to 0. ... line N: Number of operations to reduce XN to 0.
So how should I go about doing this?
Code:
#include <bits/stdc++.h>
using namespace std;
int main(){
int N;
cin >> N;
for (int i = 0; i < N; i++){
int A, count = 0;
cin >> A;
while (A > 0){
if (A%2 == 0){
A /= 2;
count++;
}
else if (A%3 == 0){
A /= 3;
count++;
}
else{
A--;
count++;
}
}
cout << count << "\n";
}
}
This code which I currently have in mind does not work for some cases(meaning I do not output the desired solution, and that the code is a working code), say Xi = 10. My code does 10/2, then -1, then /2, then /2 then -1, so it is 5 operations. However, the optimal is 10 -1, /3, /3 again, then -1, which is 4 operations. Anyone has any idea how I should code my solution to this problem? Thanks! Any help is appreciated!

You said dynamic programming:
std::vector<int> v{0};
for (int i = 1; i != N + 1; ++i) {
v.push_back(v.back() + 1);
if (i % 2 == 0) {
v.back() = std::min(v.back(), v[i / 2] + 1);
}
if (i % 3 == 0) {
v.back() = std::min(v.back(), v[i / 3] + 1);
}
}
return v.back();

Related

How can I reduce the time complexity of an algorithm in c++?

The following code takes in an integer t and then takes in 3 more integers t times and returns the maximum number of times you can subtract 1 from two different integers at the same time, whereas the program stops when there is only 1 integer above 0 remaining. I have solved the problem, but I want to reduce the time complexity of the code and I don't know how.
#include <bits/stdc++.h>
using namespace std;
int main() {
long long t, r, g, b, arr[1000], count = 0;
bool isMax=true;
cin >> t;
for (long long i = 0; i < t; i++) {
cin >> r >> g >> b;
arr[0] = r;
arr[1] = g;
arr[2] = b;
for (long long j = 0; j < 3; j++) {
for (long long k = 0; k < 2; k++) {
if (arr[k] > arr[k + 1]) {
long long a = arr[k];
long long b = arr[k + 1];
arr[k] = b;
arr[k + 1] = a;
}
}
}
count = 0;
if (arr[2] == 1) {
cout << 1 << endl;
} else if (arr[0] + arr[1] <= arr[2]) {
cout << arr[0] + arr[1] << endl;
} else {
while (arr[0] > 0) {
while (isMax && arr[0] > 0) {
arr[2]--;
arr[0]--;
count++;
if (arr[2] < arr[1]) {
isMax = false;
}
}
while (!isMax && arr[0] > 0) {
arr[1]--;
arr[0]--;
count++;
if (arr[1] < arr[2]) {
isMax = true;
}
}
}
while (arr[2] > 0 && arr[1] > 0) {
arr[2]--;
arr[1]--;
count++;
}
cout << count << endl;
}
}
}
How can I get the same output without using all these loops that increase the time complexity?
Edit: I don't want my code re-written for me, this is homework and all I want are tips and help so I can reduce the time complexity, which I don't know how to do.
Edit 2: In my algorithm, I sort the 3 numbers in ascending order, then I use a while loop to check if the smallest number (s/arr[0]) is > 0. After that, I use two more while loops to alternate between the largest and medium-size numbers (l/arr[2] and m/arr[1] respectively) and decrement from both variables s and l or m (alternating). When s becomes 0, that will mean I can just decrement l and m till one of them equals 0, and then I print the count variable (I increment count every time I decrement two of the variables).
Im not sure if i understood the problem correctly. But if i did you could optimize the algorithem the following way:
int count = 0;
int a = 20, b = 10, c = 21;
sort(a, b, c); // Function that sorts the numbers, so that a is the smallest and c is the largest
count += a; // count = 10
c -= a; // a = 10, b = 20, c = 11
if(c < b) {
float diff = b - c; // diff = 9
float distribute = diff / 2; // distribute = 4.5
count += b - ceil(distribute); // count = 25
}
else count += b;
You would have to this t times and then sum the count variables, resulting in a complexity of t.
Assuming your code is correct, you can examine exactly what your loops are doing, and look at them more mathematically.
if ( arr[2] == 1 ) {
cout << 1 << endl;
} else if ( arr[0] + arr[1] <= arr[2] ) {
cout << arr[0] + arr[1] << endl;
} else {
while ( arr[0] > 0 ) {
if ( arr[2] > arr[1] ) {
long long min = std::min( std::min( arr[0], arr[2] ), arr[2] - arr[1] + 1 );
arr[0] -= min;
arr[2] -= min;
count += min;
} else {
long long min = std::min( std::min( arr[0], arr[1] ), arr[1] - arr[2] + 1 );
arr[0] -= min;
arr[1] -= min;
count += min;
}
}
count += std::min( arr[2], arr[1] );
cout << count << endl;
}
Assuming your program was correct,t his produces the same results for all inputs I tried.
I'm not sure I understood the problem correctly but if you want to know the maximum number of times you can subtract 1 until hitting zero from two elements in a three element set, I believe the answer should be the same as finding the median element of the set. For example, if I have the set
10 20 30
The maximum amount of times I can subtract 1 is 20, if I always chose to subtract from the subset {20, 30}, while the minimum would be 10, if I always choose to subtract from the subset {10, 20}.
Hope this helps! (Assuming I didn't totally misunderstand the question ^_^ ")
Edit:
After the clarifying comment, I believe all you need to do is find the minimum between the sum of the non-maximum elements and the maximum element. Consider the following examples:
If you are given the set {80, 10, 210} for example, the answer to your problem is 90, because we can subtract 10 from the subset {80, 10}, leaving us with {70, 0, 210} where we can further subtract 70 from the subset {70, 210}, leaving us with {0,0,140}, where we can perform no more operations. We have performed 80+10 = 90 subtractions by 1 In this case, max = 210 and min+med = 90
On the other hand, the consider the set {2,2,2}. We can subtract 2 from the subset {2,2}, leaving us with {0,0,2}, where we can perform no more operations. In this case, we have performed 2 subtractions by 1 Max = 2 and min+med = 4
Last example: consider the set {2,3,5}. We can subtract 2 from the subset {2,3}, leaving us with {0,1,5}, where we can the subtract 1 from the subset {1,5}, resulting in {0,0,4}, where we can perform no more operations. In this case, we have performed 2+3=5 subtractions by 1 Max = 5 and min+med = 5
If you continue performing examples in this vein, you should be able to convince yourself that the solution is always going to be min(max, min+median).

Find the number of pairs of positive integers satisfying the inequality

I'm trying to solve a programming problem where I have to display the number of positive integer solutions of the inequality x² + y² < n, where n is given by the user. I've already written a code that seems to work but not as fast as I'd like it to. Is there any way to speed it up?
My current code:
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
long long n, i, r, k, p, a;
cin >> k;
while (k--)
{
r = 0;
cin >> n;
p = sqrt(n);
for (i = 1; i <= p; i++)
{
a = sqrt(n - (i * i));
r += a;
if ((((i * i) + (a * a)) == n) && (a > 0))
{
r--;
}
}
cout << r << "\n";
}
return 0;
}
Edit:
This is a solution for this task.
The task in English:
Find the number of natural solutions (x≥1, y≥1) of the inequality x²+y² < n, where 0 < n < 2147483647. For example, for n=10 there are 4 solutions: (1,1), (1,2), (2,1), (2,2).
Input
In the first line of input the number of test cases k is given. In the next k lines, there are the n values given.
Output
In the output, you have to display in separate lines the number of natural solutions of the inequality.
Example
Input:
2
10
11
Output:
4
6
Your solution seems fast already. The main possibility to reduce the time spent is to suppress the call to sqrtin the loop. This is obtained by considering that the value a = sqrt(n - (i * i)) does not vary very much from one iteration to the next one.
Here is the code:
r = 0;
p = sqrt(n);
if ((p*p) == n) p--;
a = p;
for (long long i = 1; i <= p; i++)
{
while ((n-i*i) <= a*a) {
--a;
}
r += a;
}

Improving optimization of nested loop

I'm making a simple program to calculate the number of pairs in an array that are divisible by 3 array length and values are user determined.
Now my code is perfectly fine. However, I just want to check if there is a faster way to calculate it which results in less compiling time?
As the length of the array is 10^4 or less compiler takes less than 100ms. However, as it gets more to 10^5 it spikes up to 1000ms so why is this? and how to improve speed?
#include <iostream>
using namespace std;
int main()
{
int N, i, b;
b = 0;
cin >> N;
unsigned int j = 0;
std::vector<unsigned int> a(N);
for (j = 0; j < N; j++) {
cin >> a[j];
if (j == 0) {
}
else {
for (i = j - 1; i >= 0; i = i - 1) {
if ((a[j] + a[i]) % 3 == 0) {
b++;
}
}
}
}
cout << b;
return 0;
}
Your algorithm has O(N^2) complexity. There is a faster way.
(a[i] + a[j]) % 3 == ((a[i] % 3) + (a[j] % 3)) % 3
Thus, you need not know the exact numbers, you need to know their remainders of division by three only. Zero remainder of the sum can be received with two numbers with zero remainders (0 + 0) and with two numbers with remainders 1 and 2 (1 + 2).
The result will be equal to r[1]*r[2] + r[0]*(r[0]-1)/2 where r[i] is the quantity of numbers with remainder equal to i.
int r[3] = {};
for (int i : a) {
r[i % 3]++;
}
std::cout << r[1]*r[2] + (r[0]*(r[0]-1)) / 2;
The complexity of this algorithm is O(N).
I've encountered this problem before, and while I don't find my particular solution, you could improve running times by hashing.
The code would look something like this:
// A C++ program to check if arr[0..n-1] can be divided
// in pairs such that every pair is divisible by k.
#include <bits/stdc++.h>
using namespace std;
// Returns true if arr[0..n-1] can be divided into pairs
// with sum divisible by k.
bool canPairs(int arr[], int n, int k)
{
// An odd length array cannot be divided into pairs
if (n & 1)
return false;
// Create a frequency array to count occurrences
// of all remainders when divided by k.
map<int, int> freq;
// Count occurrences of all remainders
for (int i = 0; i < n; i++)
freq[arr[i] % k]++;
// Traverse input array and use freq[] to decide
// if given array can be divided in pairs
for (int i = 0; i < n; i++)
{
// Remainder of current element
int rem = arr[i] % k;
// If remainder with current element divides
// k into two halves.
if (2*rem == k)
{
// Then there must be even occurrences of
// such remainder
if (freq[rem] % 2 != 0)
return false;
}
// If remainder is 0, then there must be two
// elements with 0 remainder
else if (rem == 0)
{
if (freq[rem] & 1)
return false;
}
// Else number of occurrences of remainder
// must be equal to number of occurrences of
// k - remainder
else if (freq[rem] != freq[k - rem])
return false;
}
return true;
}
/* Driver program to test above function */
int main()
{
int arr[] = {92, 75, 65, 48, 45, 35};
int k = 10;
int n = sizeof(arr)/sizeof(arr[0]);
canPairs(arr, n, k)? cout << "True": cout << "False";
return 0;
}
That works for a k (in your case 3)
But then again, this is not my code, but the code you can find in the following link. with a proper explanation. I didn't just paste the link since it's bad practice I think.

C++ - Code Optimization

I have a problem:
You are given a sequence, in the form of a string with characters ‘0’, ‘1’, and ‘?’ only. Suppose there are k ‘?’s. Then there are 2^k ways to replace each ‘?’ by a ‘0’ or a ‘1’, giving 2^k different 0-1 sequences (0-1 sequences are sequences with only zeroes and ones).
For each 0-1 sequence, define its number of inversions as the minimum number of adjacent swaps required to sort the sequence in non-decreasing order. In this problem, the sequence is sorted in non-decreasing order precisely when all the zeroes occur before all the ones. For example, the sequence 11010 has 5 inversions. We can sort it by the following moves: 11010 →→ 11001 →→ 10101 →→ 01101 →→ 01011 →→ 00111.
Find the sum of the number of inversions of the 2^k sequences, modulo 1000000007 (10^9+7).
For example:
Input: ??01
-> Output: 5
Input: ?0?
-> Output: 3
Here's my code:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <string.h>
#include <math.h>
using namespace std;
void ProcessSequences(char *input)
{
int c = 0;
/* Count the number of '?' in input sequence
* 1??0 -> 2
*/
for(int i=0;i<strlen(input);i++)
{
if(*(input+i) == '?')
{
c++;
}
}
/* Get all possible combination of '?'
* 1??0
* -> ??
* -> 00, 01, 10, 11
*/
int seqLength = pow(2,c);
// Initialize 2D array of integer
int **sequencelist, **allSequences;
sequencelist = new int*[seqLength];
allSequences = new int*[seqLength];
for(int i=0; i<seqLength; i++){
sequencelist[i] = new int[c];
allSequences[i] = new int[500000];
}
//end initialize
for(int count = 0; count < seqLength; count++)
{
int n = 0;
for(int offset = c-1; offset >= 0; offset--)
{
sequencelist[count][n] = ((count & (1 << offset)) >> offset);
// cout << sequencelist[count][n];
n++;
}
// cout << std::endl;
}
/* Change '?' in former sequence into all possible bits
* 1??0
* ?? -> 00, 01, 10, 11
* -> 1000, 1010, 1100, 1110
*/
for(int d = 0; d<seqLength; d++)
{
int seqCount = 0;
for(int e = 0; e<strlen(input); e++)
{
if(*(input+e) == '1')
{
allSequences[d][e] = 1;
}
else if(*(input+e) == '0')
{
allSequences[d][e] = 0;
}
else
{
allSequences[d][e] = sequencelist[d][seqCount];
seqCount++;
}
}
}
/*
* Sort each sequences to increasing mode
*
*/
// cout<<endl;
int totalNum[seqLength];
for(int i=0; i<seqLength; i++){
int num = 0;
for(int j=0; j<strlen(input); j++){
if(j==strlen(input)-1){
break;
}
if(allSequences[i][j] > allSequences[i][j+1]){
int temp = allSequences[i][j];
allSequences[i][j] = allSequences[i][j+1];
allSequences[i][j+1] = temp;
num++;
j = -1;
}//endif
}//endfor
totalNum[i] = num;
}//endfor
/*
* Sum of all Num of Inversions
*/
int sum = 0;
for(int i=0;i<seqLength;i++){
sum = sum + totalNum[i];
}
// cout<<"Output: "<<endl;
int out = sum%1000000007;
cout<< out <<endl;
} //end of ProcessSequences method
int main()
{
// Get Input
char seq[500000];
// cout << "Input: "<<endl;
cin >> seq;
char *p = &seq[0];
ProcessSequences(p);
return 0;
}
the results were right for small size input, but for bigger size input I got time CPU time limit > 1 second. I also got exceeded memory size. How to make it faster and optimal memory use? What algorithm should I use and what better data structure should I use?, Thank you.
Dynamic programming is the way to go. Imagine You are adding the last character to all sequences.
If it is 1 then You get XXXXXX1. Number of swaps is obviously the same as it was for every sequence so far.
If it is 0 then You need to know number of ones already in every sequence. Number of swaps would increase by the amount of ones for every sequence.
If it is ? You just add two previous cases together
You need to calculate how many sequences are there. For every length and for every number of ones (number of ones in the sequence can not be greater than length of the sequence, naturally). You start with length 1, which is trivial, and continue with longer. You can get really big numbers, so You should calculate modulo 1000000007 all the time. The program is not in C++, but should be easy to rewrite (array should be initialized to 0, int is 32bit, long in 64bit).
long Mod(long x)
{
return x % 1000000007;
}
long Calc(string s)
{
int len = s.Length;
long[,] nums = new long[len + 1, len + 1];
long sum = 0;
nums[0, 0] = 1;
for (int i = 0; i < len; ++i)
{
if(s[i] == '?')
{
sum = Mod(sum * 2);
}
for (int j = 0; j <= i; ++j)
{
if (s[i] == '0' || s[i] == '?')
{
nums[i + 1, j] = Mod(nums[i + 1, j] + nums[i, j]);
sum = Mod(sum + j * nums[i, j]);
}
if (s[i] == '1' || s[i] == '?')
{
nums[i + 1, j + 1] = nums[i, j];
}
}
}
return sum;
}
Optimalization
The code above is written to be as clear as possible and to show dynamic programming approach. You do not actually need array [len+1, len+1]. You calculate column i+1 from column i and never go back, so two columns are enough - old and new. If You dig more into it, You find out that row j of new column depends only on row j and j-1 of the old column. So You can go with one column if You actualize the values in the right direction (and do not overwrite values You would need).
The code above uses 64bit integers. You really need that only in j * nums[i, j]. The nums array contain numbers less than 1000000007 and 32bit integer is enough. Even 2*1000000007 can fit into 32bit signed int, we can make use of it.
We can optimize the code by nesting loop into conditions instead of conditions in the loop. Maybe it is even more natural approach, the only downside is repeating the code.
The % operator is, as every dividing, quite expensive. j * nums[i, j] is typically far smaller that capacity of 64bit integer, so we do not have to do modulo in every step. Just watch the actual value and apply when needed. The Mod(nums[i + 1, j] + nums[i, j]) can also be optimized, as nums[i + 1, j] + nums[i, j] would always be smaller than 2*1000000007.
And finally the optimized code. I switched to C++, I realized there are differences what int and long means, so rather make it clear:
long CalcOpt(string s)
{
long len = s.length();
vector<long> nums(len + 1);
long long sum = 0;
nums[0] = 1;
const long mod = 1000000007;
for (long i = 0; i < len; ++i)
{
if (s[i] == '1')
{
for (long j = i + 1; j > 0; --j)
{
nums[j] = nums[j - 1];
}
nums[0] = 0;
}
else if (s[i] == '0')
{
for (long j = 1; j <= i; ++j)
{
sum += (long long)j * nums[j];
if (sum > std::numeric_limits<long long>::max() / 2) { sum %= mod; }
}
}
else
{
sum *= 2;
if (sum > std::numeric_limits<long long>::max() / 2) { sum %= mod; }
for (long j = i + 1; j > 0; --j)
{
sum += (long long)j * nums[j];
if (sum > std::numeric_limits<long long>::max() / 2) { sum %= mod; }
long add = nums[j] + nums[j - 1];
if (add >= mod) { add -= mod; }
nums[j] = add;
}
}
}
return (long)(sum % mod);
}
Simplification
Time limit still exceeded? There is probably better way to do it. You can either
get back to the beginning and find out mathematically different way to calculate the result
or simplify actual solution using math
I went the second way. What we are doing in the loop is in fact convolution of two sequences, for example:
0, 0, 0, 1, 4, 6, 4, 1, 0, 0,... and 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,...
0*0 + 0*1 + 0*2 + 1*3 + 4*4 + 6*5 + 4*6 + 1*7 + 0*8...= 80
The first sequence is symmetric and the second is linear. It this case, the sum of convolution can be calculated from sum of the first sequence which is = 16 (numSum) and number from second sequence corresponding to the center of the first sequence, which is 5 (numMult). numSum*numMult = 16*5 = 80. We replace the whole loop with one multiplication if we are able to update those numbers in each step, which fortulately seems the case.
If s[i] == '0' then numSum does not change and numMult does not change.
If s[i] == '1' then numSum does not change, only numMult increments by 1, as we shift the whole sequence by one position.
If s[i] == '?' we add original and shiftet sequence together. numSum is multiplied by 2 and numMult increments by 0.5.
The 0.5 means a bit problem, as it is not the whole number. But we know, that the result would be whole number. Fortunately in modular arithmetics in this case exists inversion of two (=1/2) as a whole number. It is h = (mod+1)/2. As a reminder, inversion of 2 is such a number, that h*2=1 modulo mod. Implementation wisely it is easier to multiply numMult by 2 and divide numSum by 2, but it is just a detail, we would need 0.5 anyway. The code:
long CalcOptSimpl(string s)
{
long len = s.length();
long long sum = 0;
const long mod = 1000000007;
long numSum = (mod + 1) / 2;
long long numMult = 0;
for (long i = 0; i < len; ++i)
{
if (s[i] == '1')
{
numMult += 2;
}
else if (s[i] == '0')
{
sum += numSum * numMult;
if (sum > std::numeric_limits<long long>::max() / 4) { sum %= mod; }
}
else
{
sum = sum * 2 + numSum * numMult;
if (sum > std::numeric_limits<long long>::max() / 4) { sum %= mod; }
numSum = (numSum * 2) % mod;
numMult++;
}
}
return (long)(sum % mod);
}
I am pretty sure there exists some simple way to get this code, yet I am still unable to see it. But sometimes path is the goal :-)
If a sequence has N zeros with indexes zero[0], zero[1], ... zero[N - 1], the number of inversions for it would be (zero[0] + zero[1] + ... + zero[N - 1]) - (N - 1) * N / 2. (you should be able to prove it)
For example, 11010 has two zeros with indexes 2 and 4, so the number of inversions would be 2 + 4 - 1 * 2 / 2 = 5.
For all 2^k sequences, you can calculate the sum of two parts separately and then add them up.
1) The first part is zero[0] + zero[1] + ... + zero[N - 1]. Each 0 in the the given sequence contributes index * 2^k and each ? contributes index * 2^(k-1)
2) The second part is (N - 1) * N / 2. You can calculate this using a dynamic programming (maybe you should google and learn this first). In short, use f[i][j] to present the number of sequence with j zeros using the first i characters of the given sequence.

Write number as sum of given integers

Here's the problem.
Write the given number N, as sum of the given numbers, using only additioning and subtracting.
Here's an example:
N = 20
Integers = 8, 15, 2, 9, 10
20 = 8 + 15 - 2 + 9 - 10.
Here's my idea;
First idea was to use brute force, alternating plus and minus. First I calculate the number of combinations and its 2^k (where k is the nubmer of integers), because I can alternate only minus and plus. Then I run through all numbers from 1 to 2^k and I convert it to binary form. And for any 1 I use plus and for any 0 I use minus. You'll get it easier with an example (using the above example).
The number of combinations is: 2^k = 2^5 = 32.
Now I run through all numbers from 1 to 32.
So i get: 1=00001, that means: -8-15-2-9+10 = -24 This is false so I go on.
2 = 00010, which means: -8-15-2+9-10 = -26. Also false.
This method works good, but when the number of integers is too big it takes too long.
Here's my code in C++:
#include <iostream>
#include <cmath>
using namespace std;
int convertToBinary(int number) {
int remainder;
int binNumber = 0;
int i = 1;
while(number!=0)
{
remainder=number%2;
binNumber=binNumber + (i*remainder);
number=number/2;
i=i*10;
}
return binNumber;
}
int main()
{
int N, numberOfIntegers, Combinations, Binary, Remainder, Sum;
cin >> N >> numberOfIntegers;
int Integers[numberOfIntegers];
for(int i = 0; i<numberOfIntegers; i++)
{
cin >>Integers[i];
}
Combinations = pow(2.00, numberOfIntegers);
for(int i = Combinations-1; i>=Combinations/2; i--) // I use half of the combinations, because 10100 will compute the same sum as 01011, but in with opposite sign.
{
Sum = 0;
Binary = convertToBinary(i);
for(int j = 0; Binary!=0; j++)
{
Remainder = Binary%10;
Binary = Binary/10;
if(Remainder==1)
{
Sum += Integers[numberOfIntegers-1-j];
}
else
{
Sum -= Integers[numberOfIntegers-1-j];
}
}
if(N == abs(Sum))
{
Binary = convertToBinary(i);
for(int j = 0; Binary!=0; j++)
{
Remainder = Binary%10;
Binary = Binary/10;
if(Sum>0)
{
if(Remainder==1)
{
cout << "+" << Integers[numberOfIntegers-1-j];
}
else
{
cout << "-" << Integers[numberOfIntegers-1-j];
}
}
else
{
if(Remainder==1)
{
cout << "-" << Integers[numberOfIntegers-1-j];
}
else
{
cout << "+" << Integers[numberOfIntegers-1-j];
}
}
}
break;
}
}
return 0;
}
Since this is typical homework, I'm not going to give the complete answer. But consider this:
K = +a[1] - a[2] - a[3] + a[4]
can be rewritten as
a[0] = K
a[0] + a[2] + a[3] = a[1] + a[4]
You now have normal subset sums on both sides.
So what you are worried about is you complexity .
Lets analyse what optimisations can be done.
Given n numbers in a[n] and target Value T;
And it is sure one combination of adding and subtracting gives you T ;
So Sigma(m*a[k]) =T where( m =(-1 or 1) and 0 >= k >= n-1 )
This just means ..
It can written as
(sum of Some numbers in array) = (Sum of remaining numbers in array) + T
Like in your case..
8+15-2+9-10=20 can be written as
8+15+9= 20+10+2
So Sum of all numbers including target = 64 // we can cal that .. :)
So half of it is 32 as
Which if further written as 20+(somthing)=32
which is 12 (2+10) in this case.
Your problem can be reduced to Finding the numbers in an array whose sum is 12 in this case
So your problem now can be reduced as find the combination of numbers whose sum is k (which you can calculate as described above k=12 .) For Which the complexity is O(log (n )) n as size of array , Keep in mind that you have to sort array and use binary search based algo for getting O(log(n)).
So as complexity can be made from O(2^n) to O((N+1)logN)as sorting included.
This takes static input as you have provided and i have written using core java
public static void main(String[] args) {
System.out.println("Enter number");
Scanner sc = new Scanner(System.in);
int total = 0;
while (sc.hasNext()) {
int[] array = new int[5] ;
for(int m=0;m<array.length;m++){
array[m] = sc.nextInt();
}
int res =array[0];
for(int i=0;i<array.length-1;i++){
if((array[i]%2)==1){
res = res - array[i+1];
}
else{
res =res+array[i+1];
}
}
System.out.println(res);
}
}