Selection of maximum sub-array from the array - c

Given an array of length n, it is required to find the maximum sum of elements one can choose if it is not allowed to choose more than two consecutive elements of the array. For example;
n=5;
arr[5] = {10,3,5,7,3};
Output : 23
10+3+7+3=23
So I have written this code;
#include <stdio.h>
#include <stdlib.h>
int max=0;
void solve(int arr[],int ind,int sum,int n,int count)
{
if(ind==n){
if(sum>max)
max=sum;
}
else{
sum+=arr[ind];
if(ind==n-1)
solve(arr,ind+1,sum,n,1);
if(ind==n-2 && count>1)
solve(arr,ind+2,sum,n,1);
if(ind<n-1 && count<2){
count++;
solve(arr,ind+1,sum,n,count);
}
if(ind<n-2)
solve(arr,ind+2,sum,n,1);
if(ind<n-3)
solve(arr,ind+3,sum,n,1);
}
}
int main()
{
int n;
scanf("%d",&n);
int i=0,arr[n];
while(i<n){
scanf("%d",&arr[i]);
i++;
}
int count=1;
//going into all three possibilities
solve(arr,0,0,n,count);
solve(arr,1,0,n,count);
solve(arr,2,0,n,count);
printf("%d\n",max);
return 0;
}
This program produces the expected outputs for n<1000 but shows runtime error (SIGSEGV) for larger inputs. What may be the reason?
More effective solutions are also welcome.....

use dynamic programming
DP[i]: maximum from "i" index
there are 7 cases:
1- use the first and second elements
2- use the second and third elements
3- use the first and third elements
4- use only the first element
5- use only the second element
6- use only the third element
7- use none of the elements
int F(int[] a)
{
if (a.Length == 1)
{
return Max(a[0], 0);
}
int n = a.Length;
int[] DP = new int[n];
DP[n - 1] = Max(a[n - 1], 0);
DP[n - 2] = DP[n - 1] + Max(a[n - 2], 0);
for (int i = n - 3; i >= 0; i--)
{
DP[i] = Max(a[i], 0) + Max(a[i + 1], 0) + (i + 3 < n ? DP[i + 3] : 0);// first and second
DP[i] = Max(DP[i], Max(a[i + 1], 0) + Max(a[i + 2], 0) + (i + 4 < n ? DP[i + 4] : 0));// second and third
DP[i] = Max(DP[i], Max(a[i + 0], 0) + Max(a[i + 2], 0) + (i + 4 < n ? DP[i + 4] : 0));// first and third
DP[i] = Max(DP[i], Max(a[i + 0], 0) + (i + 2 < n ? DP[i + 2] : 0));// first
DP[i] = Max(DP[i], Max(a[i + 1], 0) + (i + 3 < n ? DP[i + 3] : 0));// second
DP[i] = Max(DP[i], Max(a[i + 2], 0) + (i + 4 < n ? DP[i + 4] : 0));// third
DP[i] = Max(DP[i], DP[i + 1]);// none
}
return DP[0];
}
example1:
int[] a = new int[] { 10, 3, 5, 7, 3 };
writer.WriteLine(F(a));
output:
23
example2:
int[] a = new int[] { 1, 5, 2, 6, 9, 8, 20, 12, 41, 3, 0, 9, 95, 6, 74, 85, 20, 14, 26, 35, 14, 72, 15 };
writer.WriteLine(F(a));
output:
496
Implementation in C

This problem has a fairly simple dynamic programming solution.
Each item in the array represents a binary choice: it can either be selected or not. But if two consecutive items are selected, then the next item cannot be selected. So for each item in the array we need to keep track of three sums
the best sum if the current item is not selected
the best sum if the current item is selected, and the previous item was not selected
the best sum if the current item is selected, and the previous item was selected
Here's the code:
#include <stdio.h>
#define max3(a) (a[0]>a[1] ? a[0]>a[2]?a[0]:a[2] : a[1]>a[2]?a[1]:a[2])
int main( void )
{
int array[] = { 10,3,7,55,60,62,4,2,5,42,8,9,12,5,1 };
int N = sizeof(array) / sizeof(array[0]);
int dp[N][3];
dp[0][0] = 0;
dp[0][1] = array[0];
dp[0][2] = 0;
for ( int i = 1; i < N; i++ )
{
dp[i][0] = max3(dp[i-1]);
dp[i][1] = dp[i-1][0] + array[i];
dp[i][2] = dp[i-1][1] + array[i];
}
printf( "%d\n", max3(dp[N-1]) );
}
The output of this program is 208. To understand how that was computed, take a look at the contents of the dp array:
Note that the correct path through the dp array is not known until the end. In this example, two endpoints have the same sum, so there are two paths through the array that give the same answer. The two paths represent these choices:
array: 10 3 7 55 60 62 4 2 5 42 8 9 12 5 1
red: 10 +7 +60+62 +2 +42+8 +12+5 = 208
blue: 10 +7 +60+62 +5+42 +9+12 +1 = 208

Related

Initializing an array in C

I am trying to initialize an array with this code, but it's not displaying the output, i.e
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
#include<stdio.h>
#define SIZE 10
int main() {
int array[SIZE] = {0}, i = 1;
while( i <= SIZE ) {
array[i] = 2 * i - 1;
i++;
}
return 0;
}
What am I doing wrong?
The immediate error is in the condition
i <= SIZE
note, that since arrays are zero based, array of length SIZE has items with
0, 1, 2, ..., SIZE - 1
indexes. So you can just put
while (i < SIZE)
and get (you start assigning from array[1], not from array[0])
trash, 1, 3, 5, ..., 17
However, I suggest redesign, why should we not use a typical for loop initialization?
for (int i = 0; i < SIZE; ++i)
array[i] = 2 * i + 1;
note, 2 * i + 1 - we put + since arrays are zero based, and we want the first array item - array[0] - be 1. This code provides
1, 3, 5, ..., 19
values
Edit: As Vlad from Moscow pointed out in the comments, you can change index instead of condition:
while (i <= SIZE) {
array[i - 1] = 2 * i - 1;
i++;
}
here we loop over 1, 2, ..., SIZE but assign vaue to array[0], array[1], ..., array[SIZE - 1] items
You just defined the array, you didn't print it anywhere. Try adding this before your return 0 statement.
for(int j = 0; j < SIZE; j++){
printf("%d\n", array[j]);
}

Count of strictly increasing sequence of integers

You are given two list of integers a and b of same length n, Find the count of strictly increasing sequences of integers
I[0] < I[1] < .. < I[n-1] such that min(a[i], b[i]) <= I[i] <= max(a[i], b[i]) for each i.
Eg.
a = [6,3,4,4]
b = [1,5,1,6]
Four possible solutions are possible
[1 3 4 5],
[1 3 4 6],
[2 3 4 5],
[2 3 4 6].
The length of both arrays will not exceed 100.
Each element is between 1 and 10000.```
Can someone provide a hint for this question? I am not able to figure out
You can use a dynamic programming approach here. The states of your DP will be the current index and last value ,like count_sequence(int index, int last_value) , loop through min(a[index], b[index]) to max(a[index], b[index]) ,if there is a value greater then last_value go to next index with current value like count_sequence(index+1, current_value), if you reach base case which is index>=n that means you find a sequence then return 1. Using this you can find every possible sequence.
With memorization, the complexity will be O(n*m),
n = array size, m = maximum element
JavaScript/node.js solution:
const a = [6, 3, 4, 4]
const b = [1, 5, 1, 6]
const n = a.length
let min = []
let max = []
for (let i = n - 1; i >= 0; i--) {
let itemMin = (min[i] = Math.min(a[i], b[i]))
let itemMax = (max[i] = Math.max(a[i], b[i]))
if (i > 0) {
const maxBefore = Math.max(a[i - 1], b[i - 1])
// max of before index, >= current min
if (maxBefore >= min[i]) {
itemMin = Math.min(maxBefore + 1, max[i])
}
}
if (i < n - 1) {
const minAfter = min[i + 1]
// min of after index, <= current or calculated min
if (itemMin >= minAfter) {
itemMin = Math.min(minAfter - 1, min[i])
}
// max correction
itemMax = Math.min(max[i], minAfter - 1)
}
// Test is solution possible, if not do something
if (itemMin < min[i] || itemMin > max[i]) {
throw new Error('Impossible to solve...')
}
if (itemMax < min[i] || itemMax > max[i]) {
throw new Error('Impossible to solve...')
}
// Set min and max values
min[i] = itemMin
max[i] = itemMax
}
// ***** Printing results
function printResult(min, max, str = '', item = 0) {
const n = min.length
for (let j = min[item]; j <= max[item]; j++) {
if (item < n - 1) {
printResult(min, max, `${item !== 0 ? str : ''}${j},`, item + 1)
} else {
console.log(`[${str}${j}]`)
}
}
}
printResult(min, max)
Given two arrays, one holding the min value and the other the max value for each index, you could define a simple recursive function to derive each possible increasing sequence, with the starting value at each position being the maximum of the current min value and the previously selected value plus 1.
Here's some Java code to illustrate:
static void incSeq(int[] min, int[] max, int[] res, int pos, int prev)
{
if(pos == min.length)
{
System.out.println("seq: " + Arrays.toString(res));
return;
}
for(int j = Math.max(prev+1, min[pos]); j <= max[pos]; j++)
{
res[pos] = j;
incSeq(min, max, res, pos+1, j);
}
}
However, if we consider input such as:
min = {1, 1, 1, 1}
max = {100, 100, 100, 5}
we can see that our function is going to do a lot of useless work iterating through values in the first three positions that will not be part of an increasing sequence.
We can fix this by recognizing that the maximum value we need to consider for position i is one less that the max value at position i+1. If we start at the last position and work backwards using this rule we can update the max array above to:
max = {2, 3, 4, 5}
Which will mean a lot less work for our recursive function.
Here's the complete code:
public static void main(String[] args)
{
int n = 4;
int[] a = {6,3,4,4};
int[] b = {1,5,1,6};
int[] min = new int[n];
int[] max = new int[n];
System.out.println("a: " + Arrays.toString(a));
System.out.println("b: " + Arrays.toString(b));
for(int i=0; i<n; i++)
{
min[i] = Math.min(a[i], b[i]);
max[i] = Math.max(a[i], b[i]);
}
System.out.println("min: " + Arrays.toString(min));
System.out.println("max: " + Arrays.toString(max));
// cap max values
for(int i=n-1; i>0; i--)
{
max[i-1] = Math.min(max[i-1], max[i]-1);
}
System.out.println("max: " + Arrays.toString(max) + "\n");
incSeq(min, max, new int[n], 0, 0);
}
static void incSeq(int[] min, int[] max, int[] res, int pos, int prev)
{
if(pos == min.length)
{
System.out.println("seq: " + Arrays.toString(res));
return;
}
for(int j = Math.max(prev+1, min[pos]); j <= max[pos]; j++)
{
res[pos] = j;
incSeq(min, max, res, pos+1, j);
}
}
Output:
a: [6, 3, 4, 4]
b: [1, 5, 1, 6]
min: [1, 3, 1, 4]
max: [6, 5, 4, 6]
max: [2, 3, 4, 6]
seq: [1, 3, 4, 5]
seq: [1, 3, 4, 6]
seq: [2, 3, 4, 5]
seq: [2, 3, 4, 6]

What is the minimum number of swaps needed so that the difference of sums of arrays a and b is minimum?

Given 2 arrays of integers a[] and b[] with the same size of n (1 <= n <= 100) numbered from 1 to n.
(0 <= a[i], b[i] <= 6)
You can swap any a[i] with b[i].
What is the minimum number of swaps needed so that the difference of the sums of array a[] and b[] is minimum ?
Then print out:
The number of swaps
The swapped indexes
The difference of sums of both arrays
Example
n = 6
a[] = { 1, 1, 4, 4, 0, 6 }
b[] = { 6, 3, 1, 1, 6, 1 }
Result
- 2 (The number of swaps)
- 5, 6 (The swapped indexes)
- 0 (The difference of sums of the arrays)
Explanation
If you swap a[5] with b[5] and a[6] with b[6] which requires 2 swaps, arrays a[] and b[] will become:
a[] = {1, 1, 4, 4, 6, 1}
b[] = {6, 3, 1, 1, 0, 6}
Sum of a[] is 1 + 1 + 4 + 4 + 6 + 1 = 17
Sum of b[] is 6 + 3 + 1 + 1 + 0 + 6 = 17
So the difference of the two sums is 0.
Here's an iterative method that saves the differences so far and updates the smallest list of indexes needed to swap to achieve them.
JavaScript code:
function update(obj, d, arr){
if (!obj[d] || obj[d].length > arr.length)
obj[d] = arr;
}
function f(A, B){
let diffs = {0: []};
for (let i=0; i<A.length; i++){
const newDiffs = {};
for (d in diffs){
// Swap
let d1 = Number(d) + B[i] - A[i];
if (diffs.hasOwnProperty(d1) && diffs[d1].length < diffs[d].length + 1)
update(newDiffs, d1, diffs[d1]);
else
update(newDiffs, d1, diffs[d].concat(i+1));
d1 = Number(d) + A[i] - B[i];
if (diffs.hasOwnProperty(d1) && diffs[d1].length < diffs[d].length)
update(newDiffs, d1, diffs[d1]);
else
update(newDiffs, d1, diffs[d]);
}
diffs = newDiffs;
}
console.log(JSON.stringify(diffs) + '\n\n');
let best = Infinity;
let idxs;
for (let d in diffs){
const _d = Math.abs(Number(d));
if (_d < best){
best = _d;
idxs = diffs[d];
}
}
return [best, idxs];
};
var A = [1, 1, 4, 4, 0, 6];
var B = [6, 3, 1, 1, 6, 1];
console.log(JSON.stringify(f(A, B)));
Here's a C++ implementation of mine based on Javascript answer of גלעד ברקן.
Short Explanation:
We maintain a mapping of all differences and their minimum swaps seen so far and try to extend all of the differences seen so far based on new values to get new mapping of such kind. We have 2 choices at each step when considering ith items in A and B, either consider the items as it is or swap the ith items.
Code:
#include <iostream>
#include <climits>
#include <unordered_map>
#include <vector>
using namespace std; // Pardon me for this sin
void update_keeping_existing_minimum(unordered_map<int, vector<int> >& mp, int key, vector<int>& value){
if(mp.find(key) == mp.end() || mp[key].size() > value.size())mp[key] = value;
}
// Prints minimum swaps, indexes of swaps and minimum difference of sums
// Runtime is O(2^size_of_input) = 2^1 + 2^2 .. + 2^n = 2*2^n
// This is a bruteforce implementation.
// We try all possible cases, by expanding our array 1 index at time.
// For each previous difference,
// we use new index value and expand our possible difference outcomes.
// In worst case we may get 2 unique differences never seen before for every index.
void get_minimum_swaps(vector<int>& a, vector<int>& b){
int n = a.size();
unordered_map<int, vector<int> > prv_differences_mp;
prv_differences_mp[0] = {}; // initial state
for(int i = 0 ; i < n ; i++){
unordered_map<int, vector<int> > new_differences_mp;
for (auto& it: prv_differences_mp) {
// possibility 1, we swap and expand previous difference
int d = it.first;
int d1 = d + b[i] - a[i];
if(prv_differences_mp.find(d1) != prv_differences_mp.end() && prv_differences_mp[d1].size() < (prv_differences_mp[d].size() + 1)){
update_keeping_existing_minimum(new_differences_mp, d1, prv_differences_mp[d1]);
} else {
// only place we are modifying the prv map, lets make a copy so that changes don't affect other calculations
vector<int> temp = prv_differences_mp[d];
temp.push_back(i+1);
update_keeping_existing_minimum(new_differences_mp, d1, temp);
}
// possibility 2, we don't swap and expand previous difference
int d2 = d + a[i] - b[i];
if(prv_differences_mp.find(d2) != prv_differences_mp.end() && prv_differences_mp[d2].size() < prv_differences_mp[d].size()){
update_keeping_existing_minimum(new_differences_mp, d2, prv_differences_mp[d2]);
} else {
update_keeping_existing_minimum(new_differences_mp, d2, prv_differences_mp[d]);
}
}
cout<<i<<":index\n";
for(auto& it: prv_differences_mp){
cout<<it.first<<": [ ";
for(auto& item: it.second)cout<<item<<" ";
cout<<"] ; ";
}
cout<<"\n";
prv_differences_mp = new_differences_mp;
}
int best = INT_MAX;
vector<int> min_swap_ans;
for(auto& it: prv_differences_mp){
int _d = it.first >= 0 ? it.first: -it.first;
if(_d < best){
best = _d;
min_swap_ans = it.second;
}
}
cout<<"Number of swaps: "<<min_swap_ans.size()<<"\n";
cout<<"Swapped indexes:\n";
for(auto idx: min_swap_ans)cout<<idx<<" ";
cout<<"\nDifference: "<<best<<"\n";
}
int main(){
vector<int> A{ 1, 1, 4, 4, 0, 6 };
vector<int> B{ 6, 3, 1, 1, 6, 1 };
get_minimum_swaps(A, B);
return 0;
}

Simple c array calculator drops the first number

This is part of my assignment. I have to make a calculator using arrays.
this is the addition part of it.
It works fine but the problem is, it drops the first digit. array size is for example 10 . it doesn't show the first digit whenever addition has remainder.
for example i want to add 5 9 7 5 3 1 0 0 0 0 with 5 0 8 6 4 2 0 0 0 0. the true answer is 11061730000 but this program shows 1061730000 (drops first 1).
how do i fix this behavior??
code:
#include <stdio.h>
#define SIZE_MAX 10
#define SIZE_USE SIZE_MAX-1
int main()
{
int i;
int inum_firstPTR[SIZE_MAX] = {5, 9, 7, 5, 3, 1, 0, 0, 0, 0};
int inum_secondPTR[SIZE_MAX] = {5, 0, 8, 6, 4, 2, 0, 0, 0, 0};
int add_resultPTR[SIZE_MAX] = {0}; //initializing result array
for (i = SIZE_USE; i >= 0; i--)
{
if (add_resultPTR[i] = inum_firstPTR[i] + inum_secondPTR[i] < 10)
{
add_resultPTR[i] = inum_firstPTR[i] + inum_secondPTR[i];
}
else
{
add_resultPTR[i] = inum_firstPTR[i] + inum_secondPTR[i] - 10;
inum_firstPTR[i - 1] = inum_firstPTR[i - 1] + 1;
}
}
puts("");
for (i = 0; i < SIZE_MAX; i++)
{
printf("%d", add_resultPTR[i]);
}
puts("");
return 0;
}
for (i = SIZE_USE; i >= 0; i--)
{
if (add_resultPTR[i] = inum_firstPTR[i] + inum_secondPTR[i] < 10)
{
add_resultPTR[i] = inum_firstPTR[i] + inum_secondPTR[i];
}
else //carry
{
if ( i > 0) // normal carry to next element
{
add_resultPTR[i] = inum_firstPTR[i] + inum_secondPTR[i] - 10;
inum_firstPTR[i - 1] = inum_firstPTR[i - 1] + 1;
}
else // element [0], no more elements to carry to
{
add_resultPTR[i] = inum_firstPTR[i] + inum_secondPTR[i];
}
}
}
addition of 5+5+carry1 is 11 but add_resultPTR[0] can only store 1 and there is no position before [0] to store carry1 therefore it only prints from 1.
moreover, 11061730000 are 11 digits how do you suppose to fit into an array of SIZE_MAX 10.
define SIZE_MAX as 11 and then to prevent from overflow store addition of inum_firstPTR[SIZE_MAX] and inum_firstPTR[SIZE_MAX] from add_resultPTR[0] to add_resultPTR[10] and print it in reverse i.e. if add_resultPTR[10] is 1 then from [10] to [0] otherwise from [9] to [0].

Replace number by sum of other numbers in a list without subtraction

I was asked:
Replace each number in a list by sum of remaining elements, the list is not sorted.
So suppose if we have a list of numbers like {2, 7, 1, 3, 8}, now we are to replace each element with sum of rest of elements. The output should be:
{(7 + 1 + 3 + 8), (2 + 1 + 3 + 8), (2 + 7 + 3 + 8), (2 + 7 + 1 + 8), (2 + 7 + 1 + 3)}
== {19, 14, 20, 18, 13}
I answered an obvious solution:
First evaluate sum of all numbers then subtract each element from sum.
So for above list sum is 2 + 7 + 1 + 3 + 8 = 21, then for output do like:
{sum - 2, sum - 7, sum - 1, sum - 3, sum - 8}
{21 - 2, 21 - 7, 21 - 1, 21 - 3, 21 - 8}
== {19, 14, 20, 18, 13}
It needs only two iterations of list.
Then Interviewer asked me: Now do it without subtraction? and I couldn't answer :(
Is other solution possible? Can some share any other trick? A better trick is possible?
Lets extra memory space can be used (I asked after a few minutes of try, even then I couldn't answer).
One possibility would be to compute prefix and suffix sums of your array and then combine the appropriate entries. This would still be O(n) but needs more memory space so I think your original method is better.
In other words, from {2, 7, 1, 3, 8} compute {2, 2+7, 2+7+1, 2+7+1+3, 2+7+1+3+8} and {2+7+1+3+8, 7+1+3+8, 1+3+8, 3+8, 8} and then add the appropriate entries.
The solution is to sum everything but the element. Then you don't have to subtract after the fact. You just skip adding the element at the current index.
Alternatively, you could get a subset of the list that excludes the element at the current index, then just sum the subset together. Pretty much the same thing as my first suggestion with more implementation detail.
C++ implementation. O(n) and done by keeping sums of all elements before and after a certain index.
#include <iostream>
int main() {
int a[] = {2,7,1,3,8};
int prefix[5]; // Sum of all values before current index
int suffix[5]; // Sum of all values after current index
prefix[0] = 0;
suffix[4] = 0;
for(int i = 1; i < 5; i++) {
prefix[i] = prefix[i-1] + a[i-1];
suffix[4 - i] = suffix[4 - i + 1] + a[4 - i + 1];
}
// Print result
for (int i = 0; i < 5; i++) {
std::cout << prefix[i] + suffix[i] << " ";
}
std::cout << std::endl;
}
I can't think anything better than yours.
But how about this :
Create a (n-1)xn matrix:
[ 2, 7, 1, 3, 8 ]
| 7, 1, 3, 8, 2 | rotate by 1
| 1, 3, 8, 2, 7 | by 2
| 3, 8, 2, 7, 1 | by 3
| 8, 2, 7, 1, 3 | by 4
Then Sum up the columns
C++'s std::rotate_copy can be used to create matrix
std::vector<int> v1 {2, 7, 1, 3, 8 };
std::vector<int> v2 (v1.size());
int i,j;
std::vector< std::vector<int> > mat;
for (int i=1; i<v1.size();++i){
std::rotate_copy(v1.begin(),v1.begin()+i,v1.end(),v2.begin());
mat.push_back(v2);
}
for(j=0;j<v1.size();++j)
for(i=0;i<v1.size()-2;++i)
v2[j]+=mat[i][j];
for(i=0;i<v2.size();++i)
std::cout<<v2[i]<<" ";
#include <iostream.h>
#include <stdio.h>
int main() {
int a[] = {2,7,1,3,8};
int sum[5]={0};
for(int j = 0; j < 5; j++){
for(int i = 1; i < 5; i++) {
sum[j]=sum[j]+a[(j+i+5)%5];
}
printf("%d ", sum[j]); }
}
Instead of subtracting the element you can add the element multiplied by -1. Multiplication and addition are allowed operations, I guess.

Resources