Given an array arr[] of positive integers. The task is to find minimum sum subsequence from the array such that at least one value among all groups of four consecutive elements is picked.
Examples :
Input: arr[] = {1, 2, 3, 4, 5, 6, 7, 8}
Output: 6
6 is sum of output subsequence {1, 5}
Note that we have following subarrays of four
consecutive elements
{(1, 2, 3, 4),
(2, 3, 4, 5),
(3, 4, 5, 6)
(4, 5, 6, 7)
(5, 6, 7, 8)}
Our subsequence {1, 5} has an element from
all above groups of four consecutive elements.
And this subsequence is minimum sum such
subsequence.
Input : arr[] = {1, 2, 3, 3, 4, 5, 6, 1}
Output : 4
The subsequence is {3, 1}. Here we consider
second three.
Input: arr[] = {1, 2, 3, 2, 1}
Output: 2
The subsequence can be {1, 1} or {2}
Input: arr[] = {6, 7, 8}
Output: 6
Input: arr[] = {6, 7}
Output: 6
The idea is similar to LIS problem. We store minimum sum subsequence ending with every element of arr[]. We finally return minimum of last four values.
dp[i] stores minimum sum subsequence (with at least
one of every four consecutive elements) of arr[0..i]
such that arr[i] is part of the solution. Note that
this may not be the best solution for subarray
arr[0..i].
We can recursively compute dp[i] using below formula
dp[i] = arr[i] + min(dp[i-1], dp[i-2], dp[i-3], dp[i-4])
Finally we return minimum of dp[n-1], dp[n-2],
dp[n-4] and dp[n-3]
OR
///Idea is simple store values of first 4 numbers in four variables
let arr[] = {5,6,7,8,9}
a=5;
b=6;
c=7;
d=8;
now Imagine if size is only five then what are the possible sets we can have?
{5,6,7,8} and {6,7,8,9}
if you can simply analyse these both the first three numbers in set two are common and
the first number in set 1 is different and last number in set 2 is also different
now what is the minimum sum we can have
(min(6,7,8) ,(5+9) ) why minimum of (6,7,8) because they are common
why (5+9) because we have to choose one element each from both sets ;
This is code implementation
class Solution{
public:
int minSum(int arr[], int n){
//Write your code here
if(n<=4)
return *min_element(arr, arr+n);
int a, b, c, d, e, ans;
a = arr[0];
b = arr[1];
c = arr[2];
d = arr[3];
for(int i=4; i<n; i++){
e = arr[i] + min({a, b, c, d});
a = b;
b = c;
c = d;
d = e;
}
return min({a, b, c, d, e});
}
};
copied from :chessnoobdj;
///
Below is the implementation of above idea.
C++
#include <iostream>
using namespace std;
int minSum( int arr[], int n)
{
int dp[n];
if (n == 1)
return arr[0];
if (n == 2)
return min(arr[0], arr[1]);
if (n == 3)
return min(arr[0], min(arr[1], arr[2]));
if (n == 4)
return min(min(arr[0], arr[1]),
min(arr[2], arr[3]));
dp[0] = arr[0];
dp[1] = arr[1];
dp[2] = arr[2];
dp[3] = arr[3];
for ( int i = 4; i < n; i++)
dp[i] = arr[i] + min(min(dp[i - 1], dp[i - 2]),
min(dp[i - 3], dp[i - 4]));
return min(min(dp[n - 1], dp[n - 2]),
min(dp[n - 4], dp[n - 3]));
}
int main()
{
int arr[] = { 1, 2, 3, 3, 4, 5, 6, 1 };
int n = sizeof (arr) / sizeof (arr[0]);
cout << minSum(arr, n);
return 0;
}
|
Java
import java.io.*;
class GFG {
static int minSum( int [] arr, int n)
{
int [] dp = new int [n];
if (n == 1 )
return arr[ 0 ];
if (n == 2 )
return Math.min(arr[ 0 ], arr[ 1 ]);
if (n == 3 )
return Math.min(arr[ 0 ], Math.min(arr[ 1 ], arr[ 2 ]));
if (n == 4 )
return Math.min(Math.min(arr[ 0 ], arr[ 1 ]),
Math.min(arr[ 2 ], arr[ 3 ]));
dp[ 0 ] = arr[ 0 ];
dp[ 1 ] = arr[ 1 ];
dp[ 2 ] = arr[ 2 ];
dp[ 3 ] = arr[ 3 ];
for ( int i = 4 ; i < n; i++)
dp[i] = arr[i] + Math.min(Math.min(dp[i - 1 ], dp[i - 2 ]),
Math.min(dp[i - 3 ], dp[i - 4 ]));
return Math.min(Math.min(dp[n - 1 ], dp[n - 2 ]),
Math.min(dp[n - 4 ], dp[n - 3 ]));
}
static public void main(String[] args)
{
int [] arr = { 1 , 2 , 3 , 3 , 4 , 5 , 6 , 1 };
int n = arr.length;
System.out.println(minSum(arr, n));
}
}
|
Python3
def minSum(arr, n):
dp = [ 0 ] * n
if (n = = 1 ):
return arr[ 0 ]
if (n = = 2 ):
return min (arr[ 0 ], arr[ 1 ])
if (n = = 3 ):
return min (arr[ 0 ],
min (arr[ 1 ], arr[ 2 ]))
if (n = = 4 ):
return min ( min (arr[ 0 ], arr[ 1 ]),
min (arr[ 2 ], arr[ 3 ]))
dp[ 0 ] = arr[ 0 ]
dp[ 1 ] = arr[ 1 ]
dp[ 2 ] = arr[ 2 ]
dp[ 3 ] = arr[ 3 ]
for i in range ( 4 , n):
dp[i] = arr[i] + min ( min (dp[i - 1 ], dp[i - 2 ]),
min (dp[i - 3 ], dp[i - 4 ]))
return min ( min (dp[n - 1 ], dp[n - 2 ]),
min (dp[n - 4 ], dp[n - 3 ]))
if __name__ = = "__main__" :
arr = [ 1 , 2 , 3 , 3 , 4 , 5 , 6 , 1 ]
n = len (arr)
print (minSum(arr, n))
|
C#
using System;
class GFG {
static int minSum( int [] arr, int n)
{
int [] dp = new int [n];
if (n == 1)
return arr[0];
if (n == 2)
return Math.Min(arr[0], arr[1]);
if (n == 3)
return Math.Min(arr[0], Math.Min(arr[1], arr[2]));
if (n == 4)
return Math.Min(Math.Min(arr[0], arr[1]),
Math.Min(arr[2], arr[3]));
dp[0] = arr[0];
dp[1] = arr[1];
dp[2] = arr[2];
dp[3] = arr[3];
for ( int i = 4; i < n; i++)
dp[i] = arr[i] + Math.Min(Math.Min(dp[i - 1], dp[i - 2]),
Math.Min(dp[i - 3], dp[i - 4]));
return Math.Min(Math.Min(dp[n - 1], dp[n - 2]),
Math.Min(dp[n - 4], dp[n - 3]));
}
static public void Main()
{
int [] arr = { 1, 2, 3, 3, 4, 5, 6, 1 };
int n = arr.Length;
Console.WriteLine(minSum(arr, n));
}
}
|
Javascript
<script>
function minSum(arr, n)
{
let dp = [];
if (n == 1)
return arr[0];
if (n == 2)
return Math.min(arr[0], arr[1]);
if (n == 3)
return Math.min(arr[0],
Math.min(arr[1], arr[2]));
if (n == 4)
return Math.min(Math.min(arr[0], arr[1]),
Math.min(arr[2], arr[3]));
dp[0] = arr[0];
dp[1] = arr[1];
dp[2] = arr[2];
dp[3] = arr[3];
for (let i = 4; i < n; i++)
dp[i] = arr[i] +
Math.min(Math.min(dp[i - 1], dp[i - 2]),
Math.min(dp[i - 3], dp[i - 4]));
return Math.min(Math.min(dp[n - 1], dp[n - 2]),
Math.min(dp[n - 4], dp[n - 3]));
}
let arr = [ 1, 2, 3, 3, 4, 5, 6, 1 ];
let n = arr.length;
document.write(minSum(arr, n));
</script>
|
Time Complexity: O(n)
Auxiliary Space: O(n)
Alternate Solution :
First of all, think that we have only four elements then our result is at least four given elements. Now, in the case, if we have more than four elements then we must maintain an array sum[] where sum[i] includes the possible minimal sum up to i-th element and also i-th element must be a part of the solution.
While computing sum[i], our base condition is that arr[i] must be a part of sum[i] and then we must have an element from last four elements. So, we can recursively compute sum[i] as sum of arr[i] and minimum (sum[i-1], sum[i-2], sum[i-3], sum[i-4]). Since there are overlapping subproblems in the recursive structure of our problem, we can use Dynamic Programming to solve this problem. And for the final result we must compute minimum of last four values of sum[] array as result must contain an element from last four elements.
C++
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
int minSum( int ar[], int n)
{
if (n <= 4)
return *min_element(ar, ar + n);
int sum[n];
sum[0] = ar[0];
sum[1] = ar[1];
sum[2] = ar[2];
sum[3] = ar[3];
for ( int i = 4; i < n; i++)
sum[i] = ar[i] + (*min_element(sum + i - 4, sum + i));
return *min_element(sum + n - 4, sum + n);
}
int main()
{
int ar[] = { 2, 4, 1, 5, 2, 3, 6, 1, 2, 4 };
int n = sizeof (ar) / sizeof (ar[0]);
cout << "Minimum sum = " << minSum(ar, n);
return 0;
}
|
Java
import java.util.Arrays;
class GFG
{
static int minSum( int ar[], int n)
{
if (n <= 4 )
return Arrays.stream(ar).min().getAsInt();
int []sum = new int [n];
sum[ 0 ] = ar[ 0 ];
sum[ 1 ] = ar[ 1 ];
sum[ 2 ] = ar[ 2 ];
sum[ 3 ] = ar[ 3 ];
for ( int i = 4 ; i < n; i++)
sum[i] = ar[i] + Arrays.stream(Arrays.copyOfRange(
sum, i - 4 , i)).min().getAsInt();
return Arrays.stream(Arrays.copyOfRange(
sum, n - 4 , n)).min().getAsInt();
}
public static void main(String[] args)
{
int ar[] = { 2 , 4 , 1 , 5 , 2 , 3 , 6 , 1 , 2 , 4 };
int n = ar.length;
System.out.println( "Minimum sum = " + minSum(ar, n));
}
}
|
Python3
def minSum(ar, n):
if (n < = 4 ):
return min (ar)
sum = [ 0 for i in range (n)]
sum [ 0 ] = ar[ 0 ]
sum [ 1 ] = ar[ 1 ]
sum [ 2 ] = ar[ 2 ]
sum [ 3 ] = ar[ 3 ]
for i in range ( 4 , n):
sum [i] = ar[i] + min ( sum [i - 4 :i])
return min ( sum [n - 4 :n])
ar = [ 2 , 4 , 1 , 5 , 2 , 3 , 6 , 1 , 2 , 4 ]
n = len (ar)
print ( "Minimum sum = " , minSum(ar, n))
|
C#
using System;
using System.Linq;
class GFG
{
static int minSum( int []ar, int n)
{
if (n <= 4)
return ar.Min();
int []sum = new int [n];
sum[0] = ar[0];
sum[1] = ar[1];
sum[2] = ar[2];
sum[3] = ar[3];
int []tempArr;
for ( int i = 4; i < n; i++)
{
tempArr = new int [4];
Array.Copy(sum, i - 4, tempArr, 0, 4);
sum[i] = ar[i] + tempArr.Min();
}
tempArr = new int [4];
Array.Copy(sum,n-4,tempArr,0,4);
return tempArr.Min();
}
public static void Main(String[] args)
{
int []ar = { 2, 4, 1, 5, 2, 3, 6, 1, 2, 4 };
int n = ar.Length;
Console.WriteLine( "Minimum sum = " +
minSum(ar, n));
}
}
|
Javascript
<script>
function minSum(ar, n)
{
if (n <= 4)
return Math.min.apply(Math,ar);
var i;
var sum = Array(n).fill(n);
sum[0] = ar[0];
sum[1] = ar[1];
sum[2] = ar[2];
sum[3] = ar[3];
for (i = 4; i < n; i++){
var temp = [];
var it;
for (it= i-4;it<i;it++)
temp.push(sum[it]);
sum[i] = ar[i] + Math.min.apply(Math,temp);
}
var temp1 = [];
for (i=n-4;i<n;i++)
temp1.push(sum[i]);
return Math.min.apply(Math,temp1);
}
var ar = [2, 4, 1, 5, 2, 3, 6, 1, 2, 4];
var n = ar.length;
document.write( "Minimum sum = " +minSum(ar, n));
</script>
|
Time Complexity: O(n)
Auxiliary Space: O(n)
Efficient approach : Space Optimization O(1)
To optimize the space complexity of the above approach we will using variables only, we can use four variables to keep track of the minimum sum subsequence for the previous four elements.
Implementation Steps:
- Implement the minSum function that takes an integer array arr and its size n as parameters.
- Handle the base cases for n equals 1, 2, 3, and 4 by returning the minimum values from the array.
- Initialize four variables (prev1, prev2, prev3, and prev4) with the first four elements of the array.
- Iterate from index 4 to n-1 and calculate the minimum sum subsequence for each element. Update the prev1, prev2, prev3, and prev4 variables in each iteration.
- After the loop, return the minimum value among the last four elements: min(min(prev1, prev2), min(prev3, prev4)).
Implementation:
C++
#include <iostream>
using namespace std;
int minSum( int arr[], int n)
{
if (n == 1)
return arr[0];
if (n == 2)
return min(arr[0], arr[1]);
if (n == 3)
return min(arr[0], min(arr[1], arr[2]));
if (n == 4)
return min(min(arr[0], arr[1]),
min(arr[2], arr[3]));
int prev1 = arr[0];
int prev2 = arr[1];
int prev3 = arr[2];
int prev4 = arr[3];
for ( int i = 4; i < n; i++)
{
int current = arr[i] + min(min(prev1, prev2),
min(prev3, prev4));
prev1 = prev2;
prev2 = prev3;
prev3 = prev4;
prev4 = current;
}
return min(min(prev1, prev2),
min(prev3, prev4));
}
int main()
{
int arr[] = {1, 2, 3, 3, 4, 5, 6, 1};
int n = sizeof (arr) / sizeof (arr[0]);
cout << "Minimum sum = " << minSum(arr, n);
return 0;
}
|
Java
import java.util.Arrays;
public class GFG {
public static int minSum( int [] arr, int n) {
if (n == 1 )
return arr[ 0 ];
if (n == 2 )
return Math.min(arr[ 0 ], arr[ 1 ]);
if (n == 3 )
return Math.min(arr[ 0 ], Math.min(arr[ 1 ], arr[ 2 ]));
if (n == 4 )
return Math.min(Math.min(arr[ 0 ], arr[ 1 ]), Math.min(arr[ 2 ], arr[ 3 ]));
int prev1 = arr[ 0 ];
int prev2 = arr[ 1 ];
int prev3 = arr[ 2 ];
int prev4 = arr[ 3 ];
for ( int i = 4 ; i < n; i++) {
int current = arr[i] + Math.min(Math.min(prev1, prev2), Math.min(prev3, prev4));
prev1 = prev2;
prev2 = prev3;
prev3 = prev4;
prev4 = current;
}
return Math.min(Math.min(prev1, prev2), Math.min(prev3, prev4));
}
public static void main(String[] args) {
int [] arr = { 1 , 2 , 3 , 3 , 4 , 5 , 6 , 1 };
int n = arr.length;
System.out.println( "Minimum sum = " + minSum(arr, n));
}
}
|
Python3
def min_sum(arr):
n = len (arr)
if n = = 1 :
return arr[ 0 ]
if n = = 2 :
return min (arr[ 0 ], arr[ 1 ])
if n = = 3 :
return min (arr[ 0 ], min (arr[ 1 ], arr[ 2 ]))
if n = = 4 :
return min ( min (arr[ 0 ], arr[ 1 ]), min (arr[ 2 ], arr[ 3 ]))
prev1 = arr[ 0 ]
prev2 = arr[ 1 ]
prev3 = arr[ 2 ]
prev4 = arr[ 3 ]
for i in range ( 4 , n):
current = arr[i] + min (prev1, prev2, prev3, prev4)
prev1 = prev2
prev2 = prev3
prev3 = prev4
prev4 = current
return min (prev1, prev2, prev3, prev4)
if __name__ = = "__main__" :
arr = [ 1 , 2 , 3 , 3 , 4 , 5 , 6 , 1 ]
print ( "Minimum sum =" , min_sum(arr))
|
C#
using System;
class GFG
{
static int MinSum( int [] arr, int n)
{
if (n == 1)
return arr[0];
if (n == 2)
return Math.Min(arr[0], arr[1]);
if (n == 3)
return Math.Min(arr[0], Math.Min(arr[1], arr[2]));
if (n == 4)
return Math.Min(Math.Min(arr[0], arr[1]),
Math.Min(arr[2], arr[3]));
int prev1 = arr[0];
int prev2 = arr[1];
int prev3 = arr[2];
int prev4 = arr[3];
for ( int i = 4; i < n; i++)
{
int current = arr[i] + Math.Min(Math.Min(prev1, prev2),Math.Min(prev3, prev4));
prev1 = prev2;
prev2 = prev3;
prev3 = prev4;
prev4 = current;
}
return Math.Min(Math.Min(prev1, prev2),
Math.Min(prev3, prev4));
}
static void Main()
{
int [] arr = { 1, 2, 3, 3, 4, 5, 6, 1 };
int n = arr.Length;
Console.WriteLine( "Minimum sum = " + MinSum(arr, n));
}
}
|
Javascript
function minSum(arr) {
const n = arr.length;
if (n === 1) {
return arr[0];
}
if (n === 2) {
return Math.min(arr[0], arr[1]);
}
if (n === 3) {
return Math.min(arr[0], Math.min(arr[1], arr[2]));
}
if (n === 4) {
return Math.min(Math.min(arr[0], arr[1]), Math.min(arr[2], arr[3]));
}
let prev1 = arr[0];
let prev2 = arr[1];
let prev3 = arr[2];
let prev4 = arr[3];
for (let i = 4; i < n; i++) {
const current = arr[i] + Math.min(Math.min(prev1, prev2), Math.min(prev3, prev4));
prev1 = prev2;
prev2 = prev3;
prev3 = prev4;
prev4 = current;
}
return Math.min(Math.min(prev1, prev2), Math.min(prev3, prev4));
}
const arr = [1, 2, 3, 3, 4, 5, 6, 1];
console.log( "Minimum sum =" , minSum(arr));
|
Output
Minimum sum = 4
Time Complexity: O(n)
Auxiliary Space: O(1)
Thanks to Shivam Pradhan for providing this alternate solution.
This article is contributed by Roshni Agarwal. If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.