Find minimum sum of elements in a matrix - java

Given a matrix, find the minimum sum of elements such that element is chosen from each row, and the adjacent element should not come from the same column. Assume the matrix only has 3 columns.
example 1:
[[1, 2, 3],
[1, 2, 3],
[3, 3, 1]]
minimum sum = 1 + 2 + 1 = 4 // matrix[0][0] + matrix[1][1] + matrix[2][2] or matrix[0][1] + matrix[1][0] + matrix[2][2]
example 2:
[[1, 100, 1],
[2, 99, 30],
[100, 12, 13]]
minimum sum = 1 + 2 + 12 = 15 // matrix[0][2] + matrix[1][0] + matrix[2][1]
example 3:
[[1, 2, 3],
[2, 5, 4],
[2, 3, 1],
[1, 6, 3]]
minimum sum = 2 + 2 + 1 + 1 = 6 // matrix[0][1] + matrix[1][0] + matrix[2][2] + matrix[3][0]
Here's my code:
public static int minCost(List<List<Integer>> matrix) {
// Write your code here
int rows = matrix.size();
int[] cost = findMin(matrix.get(0), -1);
int total = cost[0];
for (int i = 1; i < rows; i++){
List<Integer> row = matrix.get(i);
cost = findMin(row, cost[1]);
total += cost[0];
}
return total;
}
private static int[] findMin(List<Integer> row, int col){
int[] ans = new int[2];
int min = Integer.MAX_VALUE;
for (int i = 0; i < row.size(); i++) {
if (i == col){
continue;
}
if (row.get(i) < min) {
min = row.get(i);
ans[0] = min;
ans[1] = i;
}
}
return ans;
}
I initially approached this question with Greedy, which is to find the minimum element in a row and the column of the element is different from that of the previous element.
This method does not satisfy examples 2 and 3. I think dynamic programming would be the way to approach this problem but I am not sure how to construct the mem part. How to actually solve this problem with dynamic programming? Thanks in advance!

Yes you need to identify the recursive structure as you have specified in one of your comments.
You could identify as follows:
Lets say you are currently on a row row and the previous column you chose was prevcol then you need to choose a value that is not in the previous column and recurse on the remaining rows and get the minimum of all such values i.e. each time you choose a column that is not previous column and recurse on remaining rows by specifying the prev column chosen was that column you chose just now.
Look at this recursive equation to understand more:
f( arr, row, prevcol ) = minimum of ( for all col not equal to prevcol ( arr[row][col] + f( arr, row + 1, col ) )
you see how to specify the next row and previous column chosen in the call f(arr, row +1, col ) ?
The base condition is if row == arr.length i.e. no rows remaining then result is 0.
And you memoize the values that you get for each combination of row and prevcol
Java code would be :
private static int f( int[][] arr, int row, int prevCol ) {
if ( row == arr.length ) return 0;
int C = arr[row].length;
if ( dp[row][prevCol+1] != Integer.MAX_VALUE ) return dp[row][prevCol+1];
int res = Integer.MAX_VALUE;
for ( int j = 0; j < C; j++ ) {
if ( j != prevCol ) {
int val = arr[row][j] + f ( arr, row + 1, j );
res = Math.min ( res, val );
}
}
dp[row][prevCol+1] = res;
return res;
}
You need to instantiate dp array like:
dp = new int[arr.length][arr[0].length+1];
for ( int[] r : dp ) Arrays.fill(r, Integer.MAX_VALUE);
and you call the function like:
f( arr, 0, -1 ) where 0 is the starting row and -1 is the prevcol. Because prevcol starts with -1 you need to store the value in dp[row][prevcol+1]
and also for your third example the answer is 6 not 9.
row = 0, col = 1 : 2
row = 1, col = 0 : 2
row = 2, col = 2 : 1
row = 3, col = 0 : 1
2 + 2 + 1 + 1 = 6

Thank you so much #SomeDude
This is my python implementation of the same..
import math
def mincost(arr,row,prevcol,n,k):
if row == len(arr):
return 0
C = len(arr[row])
dp = [[math.inf for x in range(k+1)] for y in range(n)]
if dp[row][prevcol+1] != math.inf:
return dp[row][prevcol+1]
res = math.inf
for j in range(C):
if j != prevcol:
val = arr[row][j] + mincost(arr,row+1,j,n,k)
res = min(res,val)
dp[row][prevcol+1] = res
return res
I checked for all the above testcases specifed by #bonus, it works.

Related

Insertionsort for Array with permutation (Java)

So I have this array which I have to sort with Insertionssort:
( 4 1 2 3 )= arr[0] ,
( 1 2 3 4 )=arr[1] ,
( 4 3 2 1 ) = arr[2],
( 3 1 2 4 )= arr[3] ,
( 4 3 1 2 ) = arr[4] ,
( 2 1 3 4 ) = arr[5] ,
( 4 1 3 2 ) = arr[6] ,
( 1 4 2 3 )= arr[7]
One array will be swapped with another if the difference between value 1 - 4 of array 1 and the difference between value 1-4 of array 2 is higher. For example: arr[0] < arr[1], because 1(4-3) < 3(4-1). If the difference is the same the values will be compared: for example: arr[5] & arr[6] have the same difference(2) but arr[6].value(1) > arr[5].value(1) --> swap.
so the sorted array will look like this:
(3,1,2,4) < (4,1,2,3) < (1,4,2,3) < (2,1,3,4) < (4,1,3,2) < (4,3,1,2) < (1,2,3,4) < (4,3,2,1)
I have this methode atm, where is just checked the first criteria:
public int insertionsort(permutation[] arr, int gap) {
int count = 0;
for (int i = gap; i<arr.length-1; i++) {
count++;
permutation new = arr[i];
int k = i;
System.out.println("K: " + k);
System.out.println("gap: "+ gap);
while(Math.abs(arr[i].value(1)-arr[i].value(4)) > Math.abs(arr[i-gap].value(1) -
arr[i-gap].value(4))) {
arr[k] = arr[k-gap];
k = k-gap;
System.out.println("k-gap: " + (k-gap));
}
arr[k] = new;
}
return count;
}
Now I thought my array would be sorted in the order of the small differences first but it doesnt seem right. I hope you can help me!
I'm not clear what the purpose of the gap argument is, hopefully you can incorporate it if needed, but here's a direct translation into Java of the standard Insertion Sort method.
static void sort(permutation[] perms)
{
for(int i=1; i<perms.length; i++)
{
permutation fixed = perms[i];
int j = i - 1;
while(j >= 0 && perms[j].compareTo(fixed) > 0)
{
perms[j+1] = perms[j];
j -= 1;
}
perms[j+1] = fixed;
}
}
With a guess at what the permutation class might look like:
static class permutation
{
int len;
int[] arr;
public permutation(int... vals)
{
len = vals.length;
arr = vals.clone();
}
int value(int pos)
{
return arr[pos-1];
}
public int compareTo(permutation p)
{
int cmp = Math.abs(value(1)-value(len)) - Math.abs(p.value(1)-p.value(len));
if(cmp == 0)
for(int i=1; cmp==0 && i<=len; i++)
cmp = value(i)-p.value(i);
return cmp;
}
}
Test:
permutation[] perms = {
new permutation(4,1,2,3),
new permutation(1,2,3,4),
new permutation(4,3,2,1),
new permutation(3,1,2,4),
new permutation(4,3,1,2),
new permutation(2,1,3,4),
new permutation(4,1,3,2),
new permutation(1,4,3,2)
};
sort(perms);
for(permutation p : perms)
System.out.println(Arrays.toString(p.arr));
Output:
[1, 4, 3, 2]
[3, 1, 2, 4]
[4, 1, 2, 3]
[2, 1, 3, 4]
[4, 1, 3, 2]
[4, 3, 1, 2]
[1, 2, 3, 4]
[4, 3, 2, 1]

Find the sum of product of distinct pairs in lowest Big O

I want to find the sum of product of distinct pairs in lowest Big O.
List = [3 , 2, 1 , 7, 9]
So the distinct pairs would be - (3,2) , (3,1) (3, 7), (3, 9) , (2, 1) , (2, 7), (2, 9) , (1, 7) , (1, 9) , (7, 9).
Note that - (2,3) is same as (3,2).
What I am doing:
List = [3 , 2, 1 , 7, 9]
int result = 0;
for (int inner = 0; inner < list.size()-1; inner ++){
for(int outer = inner+1; outer < list.size(); outer++){
result+= list[inner] * list[outer];
}
}
It will run in O(n^2).
I wanted to know if there is any, better solution to this which would run in time lower time than O(n^2).
Thanks.
EDIT - sum of distinct pairs -> sum of products of distinct pairs
You have the Efficient O(n) solution here:
static int findProductSum(int A[], int n)
{
// calculating array sum (a1 + a2 ... + an)
int array_sum = 0;
for (int i = 0; i < n; i++)
array_sum = array_sum + A[i];
// calcualting square of array sum
// (a1 + a2 + ... + an)^2
int array_sum_square = array_sum * array_sum;
// calcualting a1^2 + a2^2 + ... + an^2
int individual_square_sum = 0;
for (int i = 0; i < n; i++)
individual_square_sum += A[i] * A[i];
// required sum is (array_sum_square -
// individual_square_sum) / 2
return (array_sum_square - individual_square_sum) / 2;
}
// Driver code
public static void main(String[] args)
{
int A[] = {1, 3, 4};
int n = A.length;
System.out.println("sum of product of all pairs of array "
+"elements : " + findProductSum(A, n));
}
}
I think the identity
(x1+x2+...+xn)^2 =
x1^2+x2^2+...+xn^2
+2(x1x2+...+x1xn+x2x3+...+x2xn+...)
is your friend here.

Finding array values while calculating the sum of non-consecutive subarrays of size K

I am attempting to find the maximum sum of non-consecutive subarrays of length at least k.
For example an array of [1, 2, 3, 1, 7, 9] with k = 2 should return 21 with subarrays [2,3] and [7,9] which are the 2 maximum subarrays and are non-consecutive (apart from one another) within the array.
Another example is [1, 2, 3, 4] k = 3
returns: 9, [2, 3, 4]
I am applying the method here which given an array of randomly sorted integers, calculates m number of subarrays of size k but does so by calculating a presum array making it difficult to identify the individual array values which make up the solution. As is done in this example.
Can this method be altered to show the subarrays which make up the total sum?
Below are the functions described in the above method:
// reorganize array
public static int calcProfit(List<Integer> inputArray){
int lotCount = inputArray.get(0);
inputArray.remove(0);
int maxBusiness = inputArray.get(0);
inputArray.remove(0);
// convert arrayList to int array
int[] workingArray = new int[inputArray.size()];
for(int i = 0; i < inputArray.size(); i++) {
if (inputArray.get(i) != null) {
workingArray[i] = inputArray.get(i);
}
}
System.out.println(Arrays.toString(workingArray));
int prefixArray[] = new int[lotCount + 1 - maxBusiness];
int maxArrays = (int) Math.ceil(lotCount / maxBusiness);
arraySum(prefixArray, workingArray, lotCount, maxBusiness);
System.out.println("Prefix array is" + Arrays.toString(prefixArray));
int completeArray = maxSubarray(prefixArray, maxArrays, lotCount + 1 - maxBusiness, maxBusiness, 0);
return completeArray;
}
static void arraySum(int presum[], int arr[], int n, int k)
{
for (int i = 0; i < k; i++)
presum[0] += arr[i];
// store sum of array index i to i+k
// in presum array at index i of it.
for (int i = 1; i <= n - k; i++)
presum[i] += presum[i - 1] + arr[i + k - 1] -
arr[i - 1];
}
private static int maxSubarray(int preSum[], int m, int size, int k, int start) {
// stop if array length is 0
if (m == 0) {
return 0;
}
// stop if start greater than preSum
if (start > size - 1) {
return 0;
}
System.out.println("m is : " + m + " start is : " + start);
// if including subarray of size k
int includeMax = preSum[start] + maxSubarray(preSum,m - 1, size, k, start + k);
// search next possible subarray
int excludeMax = maxSubarray(preSum, m, size, k, start + 1);
System.out.println("exclude max is : " + excludeMax + " include max is " + includeMax);
// return max
return Math.max(includeMax, excludeMax);
}
You can solve the given problem in O(n) using dynamic programming by maintaining a prefix sum array to quickly calculate the sum of a subarray of size k along with maintaining a trace array which records the action taken at each step of the array. Here's an implementation for the same: https://ideone.com/VxKzUn
The ideology behind the approach is that for every element in the array, we have an option to create our sub-array starting from this element or leave it out and move to the next element, thus giving us an optimal sub-structure the recurrence relation of which can be formulated as:
f(n) = max{ sum(arr[n], .. , arr[n + k]) + f(n + k + 1), f(n + 1) }
from collections import defaultdict
dp = defaultdict(lambda: -1)
prefixsum = []
trace = []
def getSubArraySum(i, j):
if i == 0:
return prefixsum[j]
return (prefixsum[j] - prefixsum[i - 1])
def rec(cur, arr, k):
if cur >= len(arr):
return 0
if dp[cur] != -1:
return dp[cur]
# Assuming that all the elements in the array is positive,
# else set s1 and s2 to -Infinity
s1 = -1; s2 = -1
# If we choose the subarray starting at `cur`
if cur + k - 1 < len(arr):
s1 = getSubArraySum(cur, cur + k - 1) + rec(cur + k + 1, arr, k)
# If we ignore the subarray starting at `cur`
s2 = rec(cur + 1, arr, k)
dp[cur] = max(s1, s2)
if s1 >= s2:
trace[cur] = (True, cur + k + 1)
return s1
trace[cur] = (False, cur + 1)
return s2
def getTrace(arr, trace, k):
itr = 0
subArrays = []
while itr < len(trace):
if trace[itr][0]:
subArrays.append(arr[itr : itr + k])
itr = trace[itr][1]
return subArrays
def solve(arr, k):
global dp, trace, prefixsum
dp = defaultdict(lambda: -1)
trace = [(False, 0)] * len(arr)
prefixsum = [0] * len(arr)
prefixsum[0] = arr[0]
for i in range(1, len(arr)):
prefixsum[i] += prefixsum[i - 1] + arr[i]
print("Array :", arr)
print("Max sum: ", rec(0, arr, k))
print("Subarrays: ", getTrace(arr, trace, k))
print("-- * --")
solve([1, 2, 3, 4], 3)
solve([1, 2, 3, 1, 7, 9] , 2)
The output from the above code is,
Array : [1, 2, 3, 4]
Max sum: 9
Subarrays: [[2, 3, 4]]
-- * --
Array : [1, 2, 3, 1, 7, 9]
Max sum: 21
Subarrays: [[2, 3], [7, 9]]
-- * --

Find the maximum number of flags that can be set on mountain peaks

I worked with a Codility problem provided below,
A non-empty array A consisting of N integers is given.
A peak is an array element which is larger than its neighbours. More precisely, it is an index P such that 0 < P < N − 1 and A[P − 1] < A[P] > A[P + 1].
For example, the following array A:
A[0] = 1
A[1] = 5
A[2] = 3
A[3] = 4
A[4] = 3
A[5] = 4
A[6] = 1
A[7] = 2
A[8] = 3
A[9] = 4
A[10] = 6
A[11] = 2
has exactly four peaks: elements 1, 3, 5 and 10.
You are going on a trip to a range of mountains whose relative heights are represented by array A, as shown in a figure below. You have to choose how many flags you should take with you. The goal is to set the maximum number of flags on the peaks, according to certain rules.
Flags can only be set on peaks. What's more, if you take K flags, then the distance between any two flags should be greater than or equal to K. The distance between indices P and Q is the absolute value |P − Q|.
For example, given the mountain range represented by array A, above, with N = 12, if you take:
two flags, you can set them on peaks 1 and 5;
three flags, you can set them on peaks 1, 5 and 10;
four flags, you can set only three flags, on peaks 1, 5 and 10.
You can, therefore, set a maximum of three flags in this case.
Write a function:
class Solution { public int solution(int[] A); }
that, given a non-empty array A of N integers, returns the maximum number of flags that can be set on the peaks of the array.
For example, the following array A:
A[0] = 1
A[1] = 5
A[2] = 3
A[3] = 4
A[4] = 3
A[5] = 4
A[6] = 1
A[7] = 2
A[8] = 3
A[9] = 4
A[10] = 6
A[11] = 2
the function should return 3, as explained above.
Assume that:
N is an integer within the range [1..400,000];
each element of array A is an integer within the range [0..1,000,000,000].
Complexity:
expected worst-case time complexity is O(N);
expected worst-case space complexity is O(N) (not counting the storage required for input arguments).
I walk through the solution provided below,
public static int solution(int[] A) {
int N = A.length;
/*
* P = [1, 1, 3, 3, 5, 5, 10, 10, 10, 10, 10, -1]
* */
int[] P = nextPeak(A);
int i = 1;
int result = 0;
while ((i - 1) * i <= N) {
int index = 0;
int flags = 0;
while (index < N && flags < i) {
/*
* P = [1, 1, 3, 3, 5, 5, 10, 10, 10, 10, 10, -1]
* */
index = P[index];
if (index == -1) {
break;
}
flags += 1;
index += i;
}
/*
* maximize the number of flags for the whole segment
* */
result = Math.max(result, flags);
i++;
}
return result;
}
/*
* A = [1, 1, 3, 3, 5, 5, 10, 10, 10, 10, 10, -1]
* */
public static int[] nextPeak(int[] P) {
int N = P.length;
ArrayList<Integer> peaks = new ArrayList<Integer>();
for (int i = 1; i < P.length - 1; i++) {
if (P[i] > P[i - 1] && P[i] > P[i + 1]) {
peaks.add(i);
}
}
int[] A = new int[N];
A[N - 1] = -1;
for (int i = N - 2; i >= 0; i--) {
if (peaks.contains(i)) {
A[i] = i;
} else {
A[i] = A[i + 1];
}
}
return A;
}
Generally, I understand the computation but fail to see where do we meet the condition if you take K flags, then the distance between any two flags should be greater than or equal to K.
I imagine this is inside the while condition of (i-1)*i <= N but unable to comprehend it properly. Would anyone kindly explain it to me?
Your answer is index += i; combined with the condition flags < i in the while loop.
They work the solution in reverse: walking K steps at a time, insert at most K flags.

Triangular matrix get() in one dimensional array

I want to save a triangular matrix in a 1 dim array (to minimize needed space, all zeros are left out) and create a function get() to find a specific entry from the original matrix.
For example:
Lets look at the following triangular matrix :
0 1 2 3
0 0 4 5
0 0 0 6
0 0 0 0
I am saving this matrix like this:
double[] test = {1,2,3,4,5,6};
So all the zeros are left out.
I want to write a function that gives me a value of the original matrix:
get(3,4)
should give me 6
I am checking the input to see if its out of bound and if it is below or on the diagonal.
//Checking if input is valid
if (i <= n && j <= n && i >= 1 && j >= 1){
if( j <= i ){
return 0.0;
}else {
}
}
This works.
How do I proceed though? I have trouble finding the equivalent matrix entry in my array.
Any help would be appreciated.
EDIT:
My whole code:
public class dreiecksmatrix {
int n = 4;
double[] a = {1,2,3,4,5,6};
public double get( int i, int j){
//Checking if input is valid
if (i <= n && j <= n && i >= 0 && j >= 0){
if( j <= i ){
return 0.0;
}else {
}
}
return 1.0;
}
public static void main(String [] args ){
dreiecksmatrix test = new dreiecksmatrix();
System.out.println(test.get(2,3));
}
}
Here is the sample code calculating the value of top-triange. No corner cases check like i,j >= 1 yet, but it's easy to add them.
arr = [[0, 1, 2, 3, 4],
[0, 0, 5, 6, 7],
[0, 0, 0, 8, 9],
[0, 0, 0, 0, 10],
[0, 0, 0, 0, 0]];
flatArr = [1,2,3,4,5,6,7,8,9,10];
n = 5; // matrix size
i = 1;
j = 3;
if (j <= i) {
alert(0);
} else {
pos = 0;
// find an offset caused by first (i - 1) lines
for (k = 1; k < i; k++) {
pos += n - k;
}
// find an offset in line x
pos += j - i;
// array index start from 0 so decrement value
pos = pos - 1;
alert('flatArr[' + pos + '] = ' + flatArr[pos]);
}
If you were instead to store the matrix by columns, there is a simple formula for the index into test of the i,j'th matrix element.
In your example you would have
double[] test = {1,2,4,3,5,6};
If Col(i) is the index pf the start of column i
then
Col(2) = 0
Col(3) = Col(2) + 1
..
Col(n) = Col(n-1) + n-1
Hence
Col(j) = ((j-1)*(j-2))/2
The i,j matrix element is stored i further on from the start of column j,
ie at Col(j)+i, so that you should add
return test[ ((j-1)*(j-2))/2 + i];
to your code
There is an analogous formula if you must store by rows rather than columns. It's a wee bit messier. The idea is to first figure out, starting with the last non-zero row, where the ends of the rows are solved.

Categories