Given a grid mat of dimension 2 * n, the task is to find out the maximum sum such that no two chosen numbers are adjacent, vertically, diagonally or horizontally.
Examples:
Input: mat = [[1, 4, 5], [2, 0, 0]]
Output: 7
Explanation: Choose 2 from the first column and 5 from the third column. Their sum is 7.
Input: mat = [[1, 2], [3, 4]]
Output: 4
Explanation: Choose 4 from the second column. The maximum obtainable sum is 4.
Table of Content
[Naive Approach] Using Recursion - O(2 ^ n) Time O(n) Space
The idea is to process the matrix column by column. For each column, either pick the maximum value from the current column and move to column
i + 2, or skip the current column and move to columni + 1. Recursively explore both choices and return the maximum sum obtained.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int solve(int idx, vector<vector<int>> &mat, int n)
{
if (idx >= n)
return 0;
// Take current column
int take = max(mat[0][idx], mat[1][idx]) + solve(idx + 2, mat, n);
// Skip current column
int skip = solve(idx + 1, mat, n);
return max(take, skip);
}
int maxSum(vector<vector<int>> &mat)
{
int n = mat[0].size();
return solve(0, mat, n);
}
// Driver Code
int main()
{
vector<vector<int>> mat = {{1, 4, 5}, {2, 0, 0}};
cout << maxSum(mat);
return 0;
}
import java.util.ArrayList;
import java.util.List;
public class GfG {
static int solve(int idx, List<List<Integer> > mat,
int n)
{
if (idx >= n)
return 0;
// Take current column
int take = Math.max(mat.get(0).get(idx),
mat.get(1).get(idx))
+ solve(idx + 2, mat, n);
// Skip current column
int skip = solve(idx + 1, mat, n);
return Math.max(take, skip);
}
static int maxSum(List<List<Integer> > mat)
{
int n = mat.get(0).size();
return solve(0, mat, n);
}
// Driver Code
public static void main(String[] args)
{
List<List<Integer> > mat = new ArrayList<>();
mat.add(new ArrayList<>(List.of(1, 4, 5)));
mat.add(new ArrayList<>(List.of(2, 0, 0)));
System.out.println(maxSum(mat));
}
}
def solve(idx, mat, n):
if idx >= n:
return 0
# Take current column
take = max(mat[0][idx], mat[1][idx]) + solve(idx + 2, mat, n)
# Skip current column
skip = solve(idx + 1, mat, n)
return max(take, skip)
def maxSum(mat):
n = len(mat[0])
return solve(0, mat, n)
# Driver Code
if __name__ == "__main__":
mat = [[1, 4, 5], [2, 0, 0]]
print(maxSum(mat))
using System;
using System.Collections.Generic;
public class GfG {
static int Solve(int idx, List<List<int> > mat, int n)
{
if (idx >= n)
return 0;
// Take current column
int take = Math.Max(mat[0][idx], mat[1][idx])
+ Solve(idx + 2, mat, n);
// Skip current column
int skip = Solve(idx + 1, mat, n);
return Math.Max(take, skip);
}
static int MaxSum(List<List<int> > mat)
{
int n = mat[0].Count;
return Solve(0, mat, n);
}
// Driver Code
public static void Main(string[] args)
{
List<List<int> > mat = new List<List<int> >{
new List<int>{ 1, 4, 5 },
new List<int>{ 2, 0, 0 }
};
Console.WriteLine(MaxSum(mat));
}
}
function solve(idx, mat, n)
{
if (idx >= n)
return 0;
// Take current column
let take = Math.max(mat[0][idx], mat[1][idx])
+ solve(idx + 2, mat, n);
// Skip current column
let skip = solve(idx + 1, mat, n);
return Math.max(take, skip);
}
function maxSum(mat)
{
let n = mat[0].length;
return solve(0, mat, n);
}
// Driver Code
let mat = [ [ 1, 4, 5 ], [ 2, 0, 0 ] ];
console.log(maxSum(mat));
Output
7
Time Complexity: O(2 ^ n)
Auxiliary Space: O(n)
[Expected Approach] Using Dynamic Programming - O(n) Time O(1) Space
The idea is to process the matrix column by column while maintaining three states representing whether the top cell, bottom cell, or no cell was selected in the previous column. Update these states for each column and keep only the previous column values to achieve constant extra space.
Let us understand with example:
Input: mat = [[1, 4, 5], [2, 0, 0]]
- Initialize the states using the first column as: prev_top = 1, prev_bot = 2 and prev_none = 0.
- For column 1, the states become: curr_top = 4, curr_bot = 0 and curr_none = 2.
- For column 2, the states become: curr_top = 7, curr_bot = 2 and curr_none = 4.
The final answer is max(7, 2, 4) = 7.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int maxSum(vector<vector<int>> &mat)
{
if (mat.empty() || mat[0].empty())
return 0;
int n = mat[0].size();
if (n == 1)
{
return max(mat[0][0], mat[1][0]);
}
// prev2 = dp[i-2], prev1 = dp[i-1]
// At each column i, best we can get considering cols 0..i
// dp[i] = max sum ending considerations at col i
// For each column, we have 3 choices:
// 1. Take neither cell in this column
// 2. Take top cell mat[0][i]
// 3. Take bottom cell mat[1][i]
// (can't take both in same column - they are vertically adjacent)
// dp_top[i] = max sum where last pick was mat[0][i]
// dp_bot[i] = max sum where last pick was mat[1][i]
// dp_none[i] = max sum where nothing picked at col i
int prev_top = mat[0][0];
int prev_bot = mat[1][0];
int prev_none = 0;
for (int i = 1; i < n; i++)
{
int curr_top, curr_bot, curr_none;
// Take top cell at col i:
// previous col must NOT have taken top or bottom
// (horizontal adjacency with top, diagonal adjacency with bottom)
// So previous must be none
curr_top = prev_none + mat[0][i];
// Take bottom cell at col i:
// previous col must be none (same reason)
curr_bot = prev_none + mat[1][i];
// Take nothing at col i:
// previous can be top, bottom, or none
curr_none = max({prev_top, prev_bot, prev_none});
prev_top = curr_top;
prev_bot = curr_bot;
prev_none = curr_none;
}
return max({prev_top, prev_bot, prev_none});
}
// Driver Code
int main()
{
vector<vector<int>> mat = {{1, 4, 5}, {2, 0, 0}};
cout << maxSum(mat);
return 0;
}
import java.util.*;
public class GfG {
static int maxSum(List<List<Integer> > mat)
{
if (mat.size() == 0 || mat.get(0).size() == 0)
return 0;
int n = mat.get(0).size();
if (n == 1)
return Math.max(mat.get(0).get(0),
mat.get(1).get(0));
int prevTop = mat.get(0).get(0);
int prevBot = mat.get(1).get(0);
int prevNone = 0;
for (int i = 1; i < n; i++) {
int currTop, currBot, currNone;
currTop = prevNone + mat.get(0).get(i);
currBot = prevNone + mat.get(1).get(i);
currNone = Math.max(
prevTop, Math.max(prevBot, prevNone));
prevTop = currTop;
prevBot = currBot;
prevNone = currNone;
}
return Math.max(prevTop,
Math.max(prevBot, prevNone));
}
// Driver Code
public static void main(String[] args)
{
List<List<Integer> > mat = new ArrayList<>();
mat.add(Arrays.asList(1, 4, 5));
mat.add(Arrays.asList(2, 0, 0));
System.out.println(maxSum(mat));
}
}
def maxSum(mat):
if not mat or not mat[0]:
return 0
n = len(mat[0])
if n == 1:
return max(mat[0][0], mat[1][0])
prev_top = mat[0][0]
prev_bot = mat[1][0]
prev_none = 0
for i in range(1, n):
curr_top = prev_none + mat[0][i]
curr_bot = prev_none + mat[1][i]
curr_none = max(prev_top, prev_bot, prev_none)
prev_top = curr_top
prev_bot = curr_bot
prev_none = curr_none
return max(prev_top, prev_bot, prev_none)
# Driver Code
if __name__ == "__main__":
mat = [[1, 4, 5], [2, 0, 0]]
print(maxSum(mat))
using System;
using System.Collections.Generic;
public class GfG {
public int maxSum(List<List<int> > mat)
{
if (mat.Count == 0 || mat[0].Count == 0)
return 0;
int n = mat[0].Count;
if (n == 1)
return Math.Max(mat[0][0], mat[1][0]);
int prev_top = mat[0][0];
int prev_bot = mat[1][0];
int prev_none = 0;
for (int i = 1; i < n; i++) {
int curr_top, curr_bot, curr_none;
curr_top = prev_none + mat[0][i];
curr_bot = prev_none + mat[1][i];
curr_none = Math.Max(
Math.Max(prev_top, prev_bot), prev_none);
prev_top = curr_top;
prev_bot = curr_bot;
prev_none = curr_none;
}
return Math.Max(Math.Max(prev_top, prev_bot),
prev_none);
}
// Driver Code
public static void Main()
{
List<List<int> > mat = new List<List<int> >{
new List<int>{ 1, 4, 5 },
new List<int>{ 2, 0, 0 }
};
GfG ob = new GfG();
Console.WriteLine(ob.maxSum(mat));
}
}
function maxSum(mat) {
if (mat.length === 0 || mat[0].length === 0)
return 0;
let n = mat[0].length;
if (n === 1)
return Math.max(mat[0][0], mat[1][0]);
let prev_top = mat[0][0];
let prev_bot = mat[1][0];
let prev_none = 0;
for (let i = 1; i < n; i++) {
let curr_top = prev_none + mat[0][i];
let curr_bot = prev_none + mat[1][i];
let curr_none = Math.max(prev_top, Math.max(prev_bot, prev_none));
prev_top = curr_top;
prev_bot = curr_bot;
prev_none = curr_none;
}
return Math.max(prev_top, Math.max(prev_bot, prev_none));
}
// Driver Code
let mat = [[1, 4, 5], [2, 0, 0]];
console.log(maxSum(mat));
Output
7
Time Complexity: O(n)
Auxiliary Space: O(1)