Related
I am trying to find the number of distinct vectors in a set that has the following properties:
A set is k numbers starting from 1 to k+1
D is the number of elements that can be selected
V is the sum of the elements
Examples
k=3, d=3, v=6, the result is 7;
<1, 2, 3>, <1, 3, 2>, <2, 1, 3>, <2, 2, 2>, <2, 3, 1>, <3, 1, 2>, <3, 2, 1>
k=4, d=2, v=7, the result is 2;
<3, 4>, <4, 3>
In this case, <2, 5> is not valid because 5 exceeds the value of k.
I want to find out if there is a mathematical formula to calculate the result. If there isn't a formula, how efficiently can this algorithm be implemented? I have found a rather mysterious implementation but i wonder if it can be improved upon.
public static int NumberOfDistinctVectors(int k, int d ,int v) {
if((v > k * d) || (v < d)) return 0;
if(d == 1 || v == d) return 1;
if(v == d + 1) return d;
int alpha = 1, beta = 0;
if(1 < v + k - k * d)
alpha = v + k - k * d;
if(k < v - d + 1)
beta = k;
else
beta = v - d + 1;
int sum = 0;
for(int i = alpha; i <= beta; i++) {
sum += NumberOfDistinctVectors(k, d-1, v-i);
}
return sum;
}
The problem is very related to the following:
What is the number of combinations to distribute b identical objects in c groups
where no group contains more than n objects?
which is discussed here
Just think of your numbers being made of the object (+1). So in your case
c = d, because each group corresponds to one of your numbers
b = v-d, since you need to put at least one (+1) object into each of the d groups
n = k-1, since we assume a (+1) already in each group and don't want to get larger than k
Find the code below (using appache-commons for c(N,K))
public static int NumberOfDistinctVectors(int k, int d ,int v) {
return combinations(v-d, d, k-1);
}
//combinations to distribute b identical objects to c groups
//where no group has more than n objects
public static int combinations(int b, int c, int n)
{
int sum = 0;
for(int i = 0; i <= c; i++)
{
if(b+c-1-i*(n+1) >= c-1)
sum += Math.pow(-1, i) * CombinatoricsUtils.binomialCoefficient(c, i)
* CombinatoricsUtils.binomialCoefficient(b+c-1-i*(n+1), c-1);
}
return sum;
}
Let me also quote from the original answer:
"whether this is actually any more useful than the recurrence is
another question"
Here is another way of counting that may be more efficient. It is based on the formula for permutations with repetition. I have added comments in the code hoping it makes it a bit easier to follow.
public static int NumberOfDistinctVectors2(int k, int d, int v)
{
return NumberOfDistinctVectors2_rec(1, 0, k, d, v, 1, 1);
}
public static int NumberOfDistinctVectors2_rec(
int i, /* Current number being added */
int j, /* Amount of already picked numbers */
int k, /* Maximum number that can be picked */
int d, /* Total amount of numbers to pick */
int v, /* Remaining value */
long num, /* Numerator in "permutations with repetition" formula */
long den) /* Denominator in "permutations with repetition" formula */
{
// Amount of remaining numbers to pick
int rem = d - j;
// Remaining value is too big or too small
if (v < i * rem || v > k * rem) return 0;
// If no numbers to add then we are done
if (rem == 0) return Math.toIntExact(num / den);
// If only one number to add this can be used as a "shortcut"
if (rem == 1) return d * Math.toIntExact(num / den);
// Counted permutations
int count = 0;
// Maximum amount of repetitions for the current number
int maxRep = Math.min(v / i, rem);
// Factor to multiply the numerator
int numFactor = 1;
// Factor to multiply the denominator
int denFactor = 1;
// Consider adding repetitions of the current number
for (int r = 1; r <= maxRep; r++)
{
// The numerator is the factorial of the total amount of numbers
numFactor *= (j + r);
// The denominator is the product of the factorials of the number of repetitions of each number
denFactor *= r;
// We add "r" repetitions of the current number and count all possible permutations from there
count += NumberOfDistinctVectors2_rec(i + 1, j + r, k, d, v - i * r, num * numFactor, den * denFactor);
}
// Consider permutations that do not include the current number
count += NumberOfDistinctVectors2_rec(i + 1, j, k, d, v, num, den);
return count;
}
Here is a small class testing it where this method appears to be significantly faster (see it in Rextester).
class NumberOfDistinctVectorsTest
{
// Original method
public static int NumberOfDistinctVectors(int k, int d ,int v)
{
if((v > k * d) || (v < d)) return 0;
if(d == 1 || v == d) return 1;
if(v == d + 1) return d;
int alpha = 1, beta = 0;
if(1 < v + k - k * d)
alpha = v + k - k * d;
if(k < v - d + 1)
beta = k;
else
beta = v - d + 1;
int sum = 0;
for(int i = alpha; i <= beta; i++)
{
sum += NumberOfDistinctVectors(k, d-1, v-i);
}
return sum;
}
// New method
public static int NumberOfDistinctVectors2(int k, int d, int v)
{
return NumberOfDistinctVectors2_rec(1, 0, k, d, v, 1, 1);
}
public static int NumberOfDistinctVectors2_rec(int i, int j, int k, int d, int v, long num, long den)
{
int rem = d - j;
if (v < i * rem || v > k * rem) return 0;
if (rem == 0) return Math.toIntExact(num / den);
if (rem == 1) return d * Math.toIntExact(num / den);
int count = 0;
int maxRep = Math.min(v / i, rem);
int numFactor = 1;
int denFactor = 1;
for (int r = 1; r <= maxRep; r++)
{
numFactor *= (j + r);
denFactor *= r;
count += NumberOfDistinctVectors2_rec(i + 1, j + r, k, d, v - i * r, num * numFactor, den * denFactor);
}
count += NumberOfDistinctVectors2_rec(i + 1, j, k, d, v, num, den);
return count;
}
public static void main(final String[] args)
{
// Test 1
System.out.println(NumberOfDistinctVectors(3, 3, 6));
System.out.println(NumberOfDistinctVectors2(3, 3, 6));
// Test 2
System.out.println(NumberOfDistinctVectors(4, 2, 7));
System.out.println(NumberOfDistinctVectors2(4, 2, 7));
// Test 3
System.out.println(NumberOfDistinctVectors(12, 5, 20));
System.out.println(NumberOfDistinctVectors2(12, 5, 20));
// Test runtime
long startTime, endTime;
int reps = 100;
startTime = System.nanoTime();
for (int i = 0; i < reps; i++)
{
NumberOfDistinctVectors(12, 5, 20);
}
endTime = System.nanoTime();
double t1 = ((endTime - startTime) / (reps * 1000.));
startTime = System.nanoTime();
for (int i = 0; i < reps; i++)
{
NumberOfDistinctVectors2(12, 5, 20);
}
endTime = System.nanoTime();
double t2 = ((endTime - startTime) / (reps * 1000.));
System.out.println("Original method: " + t1 + "ms");
System.out.println("New method: " + t2 + "ms");
}
}
Output:
7
7
2
2
3701
3701
Original method: 45.64331ms
New method: 5.89364ms
EDIT: New test (run on JDoodle with Apache Commons 3.6.1) including SaiBot's answer:
import org.apache.commons.math3.util.CombinatoricsUtils;
public class NumberOfDistinctVectorsTest
{
// Original method
public static int NumberOfDistinctVectors(int k, int d ,int v)
{
if((v > k * d) || (v < d)) return 0;
if(d == 1 || v == d) return 1;
if(v == d + 1) return d;
int alpha = 1, beta = 0;
if(1 < v + k - k * d)
alpha = v + k - k * d;
if(k < v - d + 1)
beta = k;
else
beta = v - d + 1;
int sum = 0;
for(int i = alpha; i <= beta; i++)
{
sum += NumberOfDistinctVectors(k, d-1, v-i);
}
return sum;
}
// jdehesa method
public static int NumberOfDistinctVectors2(int k, int d, int v)
{
return NumberOfDistinctVectors2_rec(1, 0, k, d, v, 1, 1);
}
public static int NumberOfDistinctVectors2_rec(int i, int j, int k, int d, int v, long num, long den)
{
int rem = d - j;
if (v < i * rem || v > k * rem) return 0;
if (rem == 0) return Math.toIntExact(num / den);
if (rem == 1) return d * Math.toIntExact(num / den);
int count = 0;
int maxRep = Math.min(v / i, rem);
int numFactor = 1;
int denFactor = 1;
for (int r = 1; r <= maxRep; r++)
{
numFactor *= (j + r);
denFactor *= r;
count += NumberOfDistinctVectors2_rec(i + 1, j + r, k, d, v - i * r, num * numFactor, den * denFactor);
}
count += NumberOfDistinctVectors2_rec(i + 1, j, k, d, v, num, den);
return count;
}
// SaiBot method
public static int NumberOfDistinctVectors3(int k, int d ,int v)
{
return combinations(v-d, d, k-1);
}
//combinations to distribute b identical objects to c groups
//where no group has more than n objects
public static int combinations(int b, int c, int n)
{
int sum = 0;
for(int i = 0; i <= c; i++)
{
if(b+c-1-i*(n+1) >= c-1)
sum += Math.pow(-1, i) * CombinatoricsUtils.binomialCoefficient(c, i)
* CombinatoricsUtils.binomialCoefficient(b+c-1-i*(n+1), c-1);
}
return sum;
}
public static void main(final String[] args)
{
// Test 1
System.out.println(NumberOfDistinctVectors(3, 3, 6));
System.out.println(NumberOfDistinctVectors2(3, 3, 6));
System.out.println(NumberOfDistinctVectors3(3, 3, 6));
// Test 2
System.out.println(NumberOfDistinctVectors(4, 2, 7));
System.out.println(NumberOfDistinctVectors2(4, 2, 7));
System.out.println(NumberOfDistinctVectors3(4, 2, 7));
// Test 3
System.out.println(NumberOfDistinctVectors(12, 5, 20));
System.out.println(NumberOfDistinctVectors2(12, 5, 20));
System.out.println(NumberOfDistinctVectors3(12, 5, 20));
// Test runtime
long startTime, endTime;
int reps = 100;
startTime = System.nanoTime();
for (int i = 0; i < reps; i++)
{
NumberOfDistinctVectors(12, 5, 20);
}
endTime = System.nanoTime();
double t1 = ((endTime - startTime) / (reps * 1000.));
startTime = System.nanoTime();
for (int i = 0; i < reps; i++)
{
NumberOfDistinctVectors2(12, 5, 20);
}
endTime = System.nanoTime();
double t2 = ((endTime - startTime) / (reps * 1000.));
startTime = System.nanoTime();
for (int i = 0; i < reps; i++)
{
NumberOfDistinctVectors3(12, 5, 20);
}
endTime = System.nanoTime();
double t3 = ((endTime - startTime) / (reps * 1000.));
System.out.println("Original method: " + t1 + "ms");
System.out.println("jdehesa method: " + t2 + "ms");
System.out.println("SaiBot method: " + t3 + "ms");
}
}
Output:
7
7
7
2
2
2
3701
3701
3701
Original method: 97.81325ms
jdehesa method: 7.2753ms
SaiBot method: 2.70861ms
The timings are not very stable in JDoodle (I used it because it allows for Maven dependencies), but in general SaiBot's method is the fastest by far.
Question is such that given a set of numbers we have to write a recursive program which prints all possible combination after pairing consecutive numbers or leaving them single.
<div>
Ex set 1,2,3,4,5,6
Output
<ul>
<li>1,2,3,4,5,6</li>
<li>12,3,4,5,6</li>
<li>1,23,4,5,6</li>
<li>1,2,34,5,6</li>
<li>1,2,3,45,6</li>
<li>1,2,3,4,56</li>
<li>12,34,5,6</li>
<li>12,3,45,6</li>
<li>12,3,4,56</li>
<li>1,23,45,6</li>
<li>1,23,4,56</li>
<li>1,2,34,56</li>
<li>12,34,56</li>
</div>
I use c++ to code.
Suppose the given set is a(a[0], a[1], ..., a[n - 1]), and the length of a is n
And the current answer is saved in b
void dfs(int pos, int depth)
{
if(pos >= n)
for(int i = 0; i < depth; ++i)
printf("%d%c", b[i], i == depth - 1 ? '\n' : ',');
else
{
b[depth] = a[pos];
dfs(pos + 1, depth + 1);
if(pos + 1 < n)
{
int c = 1, x = a[pos];
while(x) c *= 10, x /= 10;
b[depth] = a[pos] * c + a[pos + 1];
dfs(pos + 2, depth + 1);
}
}
}
Input: A 2-dimensional array NxN - Matrix - with positive and negative elements.Output: A submatrix of any size such that its summation is the maximum among all possible submatrices.
Requirement: Algorithm complexity to be of O(N^3)
History: With the help of the Algorithmist, Larry and a modification of Kadane's Algorithm, i managed to solve the problem partly which is determining the summation only - below in Java.
Thanks to Ernesto who managed to solve the rest of the problem which is determining the boundaries of the matrix i.e. top-left, bottom-right corners - below in Ruby.
Here's an explanation to go with the posted code. There are two key tricks to make this work efficiently: (I) Kadane's algorithm and (II) using prefix sums. You also need to (III) apply the tricks to the matrix.
Part I: Kadane's algorithm
Kadane's algorithm is a way to find a contiguous subsequence with maximum sum. Let's start with a brute force approach for finding the max contiguous subsequence and then consider optimizing it to get Kadane's algorithm.
Suppose you have the sequence:
-1, 2, 3, -2
For the brute force approach, walk along the sequence generating all possible subsequences as shown below. Considering all possibilities, we can start, extend, or end a list with each step.
At index 0, we consider appending the -1
-1, 2, 3, -2
^
Possible subsequences:
-1 [sum -1]
At index 1, we consider appending the 2
-1, 2, 3, -2
^
Possible subsequences:
-1 (end) [sum -1]
-1, 2 [sum 1]
2 [sum 2]
At index 2, we consider appending the 3
-1, 2, 3, -2
^
Possible subsequences:
-1, (end) [sum -1]
-1, 2 (end) [sum -1]
2 (end) [sum 2]
-1, 2, 3 [sum 4]
2, 3 [sum 5]
3 [sum 3]
At index 3, we consider appending the -2
-1, 2, 3, -2
^
Possible subsequences:
-1, (end) [sum -1]
-1, 2 (end) [sum 1]
2 (end) [sum 2]
-1, 2 3 (end) [sum 4]
2, 3 (end) [sum 5]
3, (end) [sum 3]
-1, 2, 3, -2 [sum 2]
2, 3, -2 [sum 3]
3, -2 [sum 1]
-2 [sum -2]
For this brute force approach, we finally pick the list with the best sum, (2, 3), and that's the answer. However, to make this efficient, consider that you really don't need to keep every one of the lists. Out of the lists that have not ended, you only need to keep the best one, the others cannot do any better. Out of the lists that have ended, you only might need to keep the best one, and only if it's better than ones that have not ended.
So, you can keep track of what you need with just a position array and a sum array. The position array is defined like this: position[r] = s keeps track of the list which ends at r and starts at s. And, sum[r] gives a sum for the subsequence ending at index r. This is optimized approach is Kadane's algorithm.
Running through the example again keeping track of our progress this way:
At index 0, we consider appending the -1
-1, 2, 3, -2
^
We start a new subsequence for the first element.
position[0] = 0
sum[0] = -1
At index 1, we consider appending the 2
-1, 2, 3, -2
^
We choose to start a new subsequence because that gives a higher sum than extending.
position[0] = 0 sum[0] = -1
position[1] = 1 sum[1] = 2
At index 2, we consider appending the 3
-1, 2, 3, -2
^
We choose to extend a subsequence because that gives a higher sum than starting a new one.
position[0] = 0 sum[0] = -1
position[1] = 1 sum[1] = 2
position[2] = 1 sum[2] = 5
Again, we choose to extend because that gives a higher sum that starting a new one.
-1, 2, 3, -2
^
position[0] = 0 sum[0] = -1
position[1] = 1 sum[1] = 2
position[2] = 1 sum[2] = 5
positions[3] = 3 sum[3] = 3
Again, the best sum is 5 and the list is from index 1 to index 2, which is (2, 3).
Part II: Prefix sums
We want to have a way to compute the sum along a row, for any start point to any endpoint. I want to compute that sum in O(1) time rather than just adding, which takes O(m) time where m is the number of elements in the sum. With some precomputing, this can be achieved. Here's how. Suppose you have a matrix:
a d g
b e h
c f i
You can precompute this matrix:
a d g
a+b d+e g+h
a+b+c d+e+f g+h+i
Once that is done you can get the sum running along any column from any start to endpoint in the column just by subtracting two values.
Part III: Bringing tricks together to find the max submatrix
Assume that you know the top and bottom row of the max submatrix. You could do this:
Ignore rows above your top row and ignore rows below your bottom
row.
With what matrix remains, consider the using sum of each column to
form a sequence (sort of like a row that represents multiple rows).
(You can compute any element of this sequence rapidly with the prefix
sums approach.)
Use Kadane's approach to figure out best subsequence in this
sequence. The indexes you get will tell you the left and right
positions of the best submatrix.
Now, what about actually figuring out the top and bottom row? Just try all possibilities. Try putting the top anywhere you can and putting the bottom anywhere you can, and run the Kadane-base procedure described previously for every possibility. When you find a max, you keep track of the top and bottom position.
Finding the row and column takes O(M^2) where M is the number of rows. Finding the column takes O(N) time where N is the number of columns. So total time is O(M^2 * N). And, if M=N, the time required is O(N^3).
About recovering the actual submatrix, and not just the maximum sum, here's what I got. Sorry I do not have time to translate my code to your java version, so I'm posting my Ruby code with some comments in the key parts
def max_contiguous_submatrix_n3(m)
rows = m.count
cols = rows ? m.first.count : 0
vps = Array.new(rows)
for i in 0..rows
vps[i] = Array.new(cols, 0)
end
for j in 0...cols
vps[0][j] = m[0][j]
for i in 1...rows
vps[i][j] = vps[i-1][j] + m[i][j]
end
end
max = [m[0][0],0,0,0,0] # this is the result, stores [max,top,left,bottom,right]
# these arrays are used over Kadane
sum = Array.new(cols) # obvious sum array used in Kadane
pos = Array.new(cols) # keeps track of the beginning position for the max subseq ending in j
for i in 0...rows
for k in i...rows
# Kadane over all columns with the i..k rows
sum.fill(0) # clean both the sum and pos arrays for the upcoming Kadane
pos.fill(0)
local_max = 0 # we keep track of the position of the max value over each Kadane's execution
# notice that we do not keep track of the max value, but only its position
sum[0] = vps[k][0] - (i==0 ? 0 : vps[i-1][0])
for j in 1...cols
value = vps[k][j] - (i==0 ? 0 : vps[i-1][j])
if sum[j-1] > 0
sum[j] = sum[j-1] + value
pos[j] = pos[j-1]
else
sum[j] = value
pos[j] = j
end
if sum[j] > sum[local_max]
local_max = j
end
end
# Kadane ends here
# Here's the key thing
# If the max value obtained over the past Kadane's execution is larger than
# the current maximum, then update the max array with sum and bounds
if sum[local_max] > max[0]
# sum[local_max] is the new max value
# the corresponding submatrix goes from rows i..k.
# and from columns pos[local_max]..local_max
# the array below contains [max_sum,top,left,bottom,right]
max = [sum[local_max], i, pos[local_max], k, local_max]
end
end
end
return max # return the array with [max_sum,top,left,bottom,right]
end
Some notes for clarification:
I use an array to store all the values pertaining to the result for convenience. You can just use five standalone variables: max, top, left, bottom, right. It's just easier to assign in one line to the array and then the subroutine returns the array with all the needed information.
If you copy and paste this code in a text-highlight-enabled editor with Ruby support you'll obviously understand it better. Hope this helps!
There are already plenty of answers, but here is another Java implementation I wrote. It compares 3 solutions:
Naïve (brute force) - O(n^6) time
The obvious DP solution - O(n^4) time and O(n^3) space
The more clever DP solution based on Kadane's algorithm - O(n^3) time and O(n^2) space
There are sample runs for n = 10 thru n = 70 in increments of 10 with a nice output comparing run time and space requirements.
Code:
public class MaxSubarray2D {
static int LENGTH;
final static int MAX_VAL = 10;
public static void main(String[] args) {
for (int i = 10; i <= 70; i += 10) {
LENGTH = i;
int[][] a = new int[LENGTH][LENGTH];
for (int row = 0; row < LENGTH; row++) {
for (int col = 0; col < LENGTH; col++) {
a[row][col] = (int) (Math.random() * (MAX_VAL + 1));
if (Math.random() > 0.5D) {
a[row][col] = -a[row][col];
}
//System.out.printf("%4d", a[row][col]);
}
//System.out.println();
}
System.out.println("N = " + LENGTH);
System.out.println("-------");
long start, end;
start = System.currentTimeMillis();
naiveSolution(a);
end = System.currentTimeMillis();
System.out.println(" run time: " + (end - start) + " ms no auxiliary space requirements");
start = System.currentTimeMillis();
dynamicProgammingSolution(a);
end = System.currentTimeMillis();
System.out.println(" run time: " + (end - start) + " ms requires auxiliary space for "
+ ((int) Math.pow(LENGTH, 4)) + " integers");
start = System.currentTimeMillis();
kadane2D(a);
end = System.currentTimeMillis();
System.out.println(" run time: " + (end - start) + " ms requires auxiliary space for " +
+ ((int) Math.pow(LENGTH, 2)) + " integers");
System.out.println();
System.out.println();
}
}
// O(N^2) !!!
public static void kadane2D(int[][] a) {
int[][] s = new int[LENGTH + 1][LENGTH]; // [ending row][sum from row zero to ending row] (rows 1-indexed!)
for (int r = 0; r < LENGTH + 1; r++) {
for (int c = 0; c < LENGTH; c++) {
s[r][c] = 0;
}
}
for (int r = 1; r < LENGTH + 1; r++) {
for (int c = 0; c < LENGTH; c++) {
s[r][c] = s[r - 1][c] + a[r - 1][c];
}
}
int maxSum = Integer.MIN_VALUE;
int maxRowStart = -1;
int maxColStart = -1;
int maxRowEnd = -1;
int maxColEnd = -1;
for (int r1 = 1; r1 < LENGTH + 1; r1++) { // rows 1-indexed!
for (int r2 = r1; r2 < LENGTH + 1; r2++) { // rows 1-indexed!
int[] s1 = new int[LENGTH];
for (int c = 0; c < LENGTH; c++) {
s1[c] = s[r2][c] - s[r1 - 1][c];
}
int max = 0;
int c1 = 0;
for (int c = 0; c < LENGTH; c++) {
max = s1[c] + max;
if (max <= 0) {
max = 0;
c1 = c + 1;
}
if (max > maxSum) {
maxSum = max;
maxRowStart = r1 - 1;
maxColStart = c1;
maxRowEnd = r2 - 1;
maxColEnd = c;
}
}
}
}
System.out.print("KADANE SOLUTION | Max sum: " + maxSum);
System.out.print(" Start: (" + maxRowStart + ", " + maxColStart +
") End: (" + maxRowEnd + ", " + maxColEnd + ")");
}
// O(N^4) !!!
public static void dynamicProgammingSolution(int[][] a) {
int[][][][] dynTable = new int[LENGTH][LENGTH][LENGTH + 1][LENGTH + 1]; // [row][col][height][width]
int maxSum = Integer.MIN_VALUE;
int maxRowStart = -1;
int maxColStart = -1;
int maxRowEnd = -1;
int maxColEnd = -1;
for (int r = 0; r < LENGTH; r++) {
for (int c = 0; c < LENGTH; c++) {
for (int h = 0; h < LENGTH + 1; h++) {
for (int w = 0; w < LENGTH + 1; w++) {
dynTable[r][c][h][w] = 0;
}
}
}
}
for (int r = 0; r < LENGTH; r++) {
for (int c = 0; c < LENGTH; c++) {
for (int h = 1; h <= LENGTH - r; h++) {
int rowTotal = 0;
for (int w = 1; w <= LENGTH - c; w++) {
rowTotal += a[r + h - 1][c + w - 1];
dynTable[r][c][h][w] = rowTotal + dynTable[r][c][h - 1][w];
}
}
}
}
for (int r = 0; r < LENGTH; r++) {
for (int c = 0; c < LENGTH; c++) {
for (int h = 0; h < LENGTH + 1; h++) {
for (int w = 0; w < LENGTH + 1; w++) {
if (dynTable[r][c][h][w] > maxSum) {
maxSum = dynTable[r][c][h][w];
maxRowStart = r;
maxColStart = c;
maxRowEnd = r + h - 1;
maxColEnd = c + w - 1;
}
}
}
}
}
System.out.print(" DP SOLUTION | Max sum: " + maxSum);
System.out.print(" Start: (" + maxRowStart + ", " + maxColStart +
") End: (" + maxRowEnd + ", " + maxColEnd + ")");
}
// O(N^6) !!!
public static void naiveSolution(int[][] a) {
int maxSum = Integer.MIN_VALUE;
int maxRowStart = -1;
int maxColStart = -1;
int maxRowEnd = -1;
int maxColEnd = -1;
for (int rowStart = 0; rowStart < LENGTH; rowStart++) {
for (int colStart = 0; colStart < LENGTH; colStart++) {
for (int rowEnd = 0; rowEnd < LENGTH; rowEnd++) {
for (int colEnd = 0; colEnd < LENGTH; colEnd++) {
int sum = 0;
for (int row = rowStart; row <= rowEnd; row++) {
for (int col = colStart; col <= colEnd; col++) {
sum += a[row][col];
}
}
if (sum > maxSum) {
maxSum = sum;
maxRowStart = rowStart;
maxColStart = colStart;
maxRowEnd = rowEnd;
maxColEnd = colEnd;
}
}
}
}
}
System.out.print(" NAIVE SOLUTION | Max sum: " + maxSum);
System.out.print(" Start: (" + maxRowStart + ", " + maxColStart +
") End: (" + maxRowEnd + ", " + maxColEnd + ")");
}
}
Here is a Java version of Ernesto implementation with some modifications:
public int[][] findMaximumSubMatrix(int[][] matrix){
int dim = matrix.length;
//computing the vertical prefix sum for columns
int[][] ps = new int[dim][dim];
for (int i = 0; i < dim; i++) {
for (int j = 0; j < dim; j++) {
if (j == 0) {
ps[j][i] = matrix[j][i];
} else {
ps[j][i] = matrix[j][i] + ps[j - 1][i];
}
}
}
int maxSum = matrix[0][0];
int top = 0, left = 0, bottom = 0, right = 0;
//Auxiliary variables
int[] sum = new int[dim];
int[] pos = new int[dim];
int localMax;
for (int i = 0; i < dim; i++) {
for (int k = i; k < dim; k++) {
// Kadane over all columns with the i..k rows
reset(sum);
reset(pos);
localMax = 0;
//we keep track of the position of the max value over each Kadane's execution
// notice that we do not keep track of the max value, but only its position
sum[0] = ps[k][0] - (i==0 ? 0 : ps[i-1][0]);
for (int j = 1; j < dim; j++) {
if (sum[j-1] > 0){
sum[j] = sum[j-1] + ps[k][j] - (i==0 ? 0 : ps[i-1][j]);
pos[j] = pos[j-1];
}else{
sum[j] = ps[k][j] - (i==0 ? 0 : ps[i-1][j]);
pos[j] = j;
}
if (sum[j] > sum[localMax]){
localMax = j;
}
}//Kadane ends here
if (sum[localMax] > maxSum){
/* sum[localMax] is the new max value
the corresponding submatrix goes from rows i..k.
and from columns pos[localMax]..localMax
*/
maxSum = sum[localMax];
top = i;
left = pos[localMax];
bottom = k;
right = localMax;
}
}
}
System.out.println("Max SubMatrix determinant = " + maxSum);
//composing the required matrix
int[][] output = new int[bottom - top + 1][right - left + 1];
for(int i = top, k = 0; i <= bottom; i++, k++){
for(int j = left, l = 0; j <= right ; j++, l++){
output[k][l] = matrix[i][j];
}
}
return output;
}
private void reset(int[] a) {
for (int index = 0; index < a.length; index++) {
a[index] = 0;
}
}
With the help of the Algorithmist and Larry and a modification of Kadane's Algorithm, here is my solution:
int dim = matrix.length;
//computing the vertical prefix sum for columns
int[][] ps = new int[dim][dim];
for (int i = 0; i < dim; i++) {
for (int j = 0; j < dim; j++) {
if (j == 0) {
ps[j][i] = matrix[j][i];
} else {
ps[j][i] = matrix[j][i] + ps[j - 1][i];
}
}
}
int maxSoFar = 0;
int min , subMatrix;
//iterate over the possible combinations applying Kadane's Alg.
for (int i = 0; i < dim; i++) {
for (int j = i; j < dim; j++) {
min = 0;
subMatrix = 0;
for (int k = 0; k < dim; k++) {
if (i == 0) {
subMatrix += ps[j][k];
} else {
subMatrix += ps[j][k] - ps[i - 1 ][k];
}
if(subMatrix < min){
min = subMatrix;
}
if((subMatrix - min) > maxSoFar){
maxSoFar = subMatrix - min;
}
}
}
}
The only thing left is to determine the submatrix elements, i.e: the top left and the bottom right corner of the submatrix. Anyone suggestion?
this is my implementation of 2D Kadane algorithm. I think it is more clear. The concept is based on just kadane algorithm. The first and second loop of the main part (that is in the bottom of the code) is to pick every combination of the rows and 3rd loop is to use 1D kadane algorithm by every following column sum (that can be computed in const time because of preprocessing of matrix by subtracting values from two picked (from combintation) rows). Here is the code:
int [][] m = {
{1,-5,-5},
{1,3,-5},
{1,3,-5}
};
int N = m.length;
// summing columns to be able to count sum between two rows in some column in const time
for (int i=0; i<N; ++i)
m[0][i] = m[0][i];
for (int j=1; j<N; ++j)
for (int i=0; i<N; ++i)
m[j][i] = m[j][i] + m[j-1][i];
int total_max = 0, sum;
for (int i=0; i<N; ++i) {
for (int k=i; k<N; ++k) { //for each combination of rows
sum = 0;
for (int j=0; j<N; j++) { //kadane algorithm for every column
sum += i==0 ? m[k][j] : m[k][j] - m[i-1][j]; //for first upper row is exception
total_max = Math.max(sum, total_max);
}
}
}
System.out.println(total_max);
I am going to post an answer here and can add actual c++ code if it is requested because I had recently worked through this. Some rumors of a divide and conqueror that can solve this in O(N^2) are out there but I haven't seen any code to support this. In my experience the following is what I have found.
O(i^3j^3) -- naive brute force method
o(i^2j^2) -- dynamic programming with memoization
O(i^2j) -- using max contiguous sub sequence for an array
if ( i == j )
O(n^6) -- naive
O(n^4) -- dynamic programming
O(n^3) -- max contiguous sub sequence
Have a look at JAMA package; I believe it will make your life easier.
Here is the C# solution. Ref: http://www.algorithmist.com/index.php/UVa_108
public static MaxSumMatrix FindMaxSumSubmatrix(int[,] inMtrx)
{
MaxSumMatrix maxSumMtrx = new MaxSumMatrix();
// Step 1. Create SumMatrix - do the cumulative columnar summation
// S[i,j] = S[i-1,j]+ inMtrx[i-1,j];
int m = inMtrx.GetUpperBound(0) + 2;
int n = inMtrx.GetUpperBound(1)+1;
int[,] sumMatrix = new int[m, n];
for (int i = 1; i < m; i++)
{
for (int j = 0; j < n; j++)
{
sumMatrix[i, j] = sumMatrix[i - 1, j] + inMtrx[i - 1, j];
}
}
PrintMatrix(sumMatrix);
// Step 2. Create rowSpans starting each rowIdx. For these row spans, create a 1-D array r_ij
for (int x = 0; x < n; x++)
{
for (int y = x; y < n; y++)
{
int[] r_ij = new int[n];
for (int k = 0; k < n; k++)
{
r_ij[k] = sumMatrix[y + 1,k] - sumMatrix[x, k];
}
// Step 3. Find MaxSubarray of this r_ij. If the sum is greater than the last recorded sum =>
// capture Sum, colStartIdx, ColEndIdx.
// capture current x as rowTopIdx, y as rowBottomIdx.
MaxSum currMaxSum = KadanesAlgo.FindMaxSumSubarray(r_ij);
if (currMaxSum.maxSum > maxSumMtrx.sum)
{
maxSumMtrx.sum = currMaxSum.maxSum;
maxSumMtrx.colStart = currMaxSum.maxStartIdx;
maxSumMtrx.colEnd = currMaxSum.maxEndIdx;
maxSumMtrx.rowStart = x;
maxSumMtrx.rowEnd = y;
}
}
}
return maxSumMtrx;
}
public static void PrintMatrix(int[,] matrix)
{
int endRow = matrix.GetUpperBound(0);
int endCol = matrix.GetUpperBound(1);
PrintMatrix(matrix, 0, endRow, 0, endCol);
}
public static void PrintMatrix(int[,] matrix, int startRow, int endRow, int startCol, int endCol)
{
StringBuilder sb = new StringBuilder();
for (int i = startRow; i <= endRow; i++)
{
sb.Append(Environment.NewLine);
for (int j = startCol; j <= endCol; j++)
{
sb.Append(string.Format("{0} ", matrix[i,j]));
}
}
Console.WriteLine(sb.ToString());
}
// Given an NxN matrix of positive and negative integers, write code to find the sub-matrix with the largest possible sum
public static MaxSum FindMaxSumSubarray(int[] inArr)
{
int currMax = 0;
int currStartIndex = 0;
// initialize maxSum to -infinity, maxStart and maxEnd idx to 0.
MaxSum mx = new MaxSum(int.MinValue, 0, 0);
// travers through the array
for (int currEndIndex = 0; currEndIndex < inArr.Length; currEndIndex++)
{
// add element value to the current max.
currMax += inArr[currEndIndex];
// if current max is more that the last maxSum calculated, set the maxSum and its idx
if (currMax > mx.maxSum)
{
mx.maxSum = currMax;
mx.maxStartIdx = currStartIndex;
mx.maxEndIdx = currEndIndex;
}
if (currMax < 0) // if currMax is -ve, change it back to 0
{
currMax = 0;
currStartIndex = currEndIndex + 1;
}
}
return mx;
}
struct MaxSum
{
public int maxSum;
public int maxStartIdx;
public int maxEndIdx;
public MaxSum(int mxSum, int mxStart, int mxEnd)
{
this.maxSum = mxSum;
this.maxStartIdx = mxStart;
this.maxEndIdx = mxEnd;
}
}
class MaxSumMatrix
{
public int sum = int.MinValue;
public int rowStart = -1;
public int rowEnd = -1;
public int colStart = -1;
public int colEnd = -1;
}
Here is my solution. It's O(n^3) in time and O(n^2) space.
https://gist.github.com/toliuweijing/6097144
// 0th O(n) on all candidate bottoms #B.
// 1th O(n) on candidate tops #T.
// 2th O(n) on finding the maximum #left/#right match.
int maxRect(vector<vector<int> >& mat) {
int n = mat.size();
vector<vector<int> >& colSum = mat;
for (int i = 1 ; i < n ; ++i)
for (int j = 0 ; j < n ; ++j)
colSum[i][j] += colSum[i-1][j];
int optrect = 0;
for (int b = 0 ; b < n ; ++b) {
for (int t = 0 ; t <= b ; ++t) {
int minLeft = 0;
int rowSum[n];
for (int i = 0 ; i < n ; ++i) {
int col = t == 0 ? colSum[b][i] : colSum[b][i] - colSum[t-1][i];
rowSum[i] = i == 0? col : col + rowSum[i-1];
optrect = max(optrect, rowSum[i] - minLeft);
minLeft = min(minLeft, rowSum[i]);
}
}
}
return optrect;
}
I would just parse the NxN array removing the -ves whatever remains is the highest sum of a sub matrix.
The question doesn't say you have to leave the original matrix intact or that the order matters.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
I found a piece of code that I was writing for interview prep few months ago.
According to the comment I had, it was trying to solve this problem:
Given some dollar value in cents (e.g. 200 = 2 dollars, 1000 = 10 dollars), find all the combinations of coins that make up the dollar value.
There are only pennies (1¢), nickels (5¢), dimes (10¢), and quarters (25¢) allowed.
For example, if 100 was given, the answer should be:
4 quarter(s) 0 dime(s) 0 nickel(s) 0 pennies
3 quarter(s) 1 dime(s) 0 nickel(s) 15 pennies
etc.
I believe that this can be solved in both iterative and recursive ways. My recursive solution is quite buggy, and I was wondering how other people would solve this problem. The difficult part of this problem was making it as efficient as possible.
I looked into this once a long time ago, and you can read my little write-up on it. Here’s the Mathematica source.
By using generating functions, you can get a closed-form constant-time solution to the problem. Graham, Knuth, and Patashnik’s Concrete Mathematics is the book for this, and contains a fairly extensive discussion of the problem. Essentially you define a polynomial where the nth coefficient is the number of ways of making change for n dollars.
Pages 4-5 of the writeup show how you can use Mathematica (or any other convenient computer algebra system) to compute the answer for 10^10^6 dollars in a couple seconds in three lines of code.
(And this was long enough ago that that’s a couple of seconds on a 75Mhz Pentium...)
Note: This only shows the number of ways.
Scala function:
def countChange(money: Int, coins: List[Int]): Int =
if (money == 0) 1
else if (coins.isEmpty || money < 0) 0
else countChange(money - coins.head, coins) + countChange(money, coins.tail)
I would favor a recursive solution. You have some list of denominations, if the smallest one can evenly divide any remaining currency amount, this should work fine.
Basically, you move from largest to smallest denominations.
Recursively,
You have a current total to fill, and a largest denomination (with more than 1 left).
If there is only 1 denomination left, there is only one way to fill the total. You can use 0 to k copies of your current denomination such that k * cur denomination <= total.
For 0 to k, call the function with the modified total and new largest denomination.
Add up the results from 0 to k. That's how many ways you can fill your total from the current denomination on down. Return this number.
Here's my python version of your stated problem, for 200 cents. I get 1463 ways. This version prints all the combinations and the final count total.
#!/usr/bin/python
# find the number of ways to reach a total with the given number of combinations
cents = 200
denominations = [25, 10, 5, 1]
names = {25: "quarter(s)", 10: "dime(s)", 5 : "nickel(s)", 1 : "pennies"}
def count_combs(left, i, comb, add):
if add: comb.append(add)
if left == 0 or (i+1) == len(denominations):
if (i+1) == len(denominations) and left > 0:
if left % denominations[i]:
return 0
comb.append( (left/denominations[i], demoninations[i]) )
i += 1
while i < len(denominations):
comb.append( (0, denominations[i]) )
i += 1
print(" ".join("%d %s" % (n,names[c]) for (n,c) in comb))
return 1
cur = denominations[i]
return sum(count_combs(left-x*cur, i+1, comb[:], (x,cur)) for x in range(0, int(left/cur)+1))
count_combs(cents, 0, [], None)
Scala function :
def countChange(money: Int, coins: List[Int]): Int = {
def loop(money: Int, lcoins: List[Int], count: Int): Int = {
// if there are no more coins or if we run out of money ... return 0
if ( lcoins.isEmpty || money < 0) 0
else{
if (money == 0 ) count + 1
/* if the recursive subtraction leads to 0 money left - a prefect division hence return count +1 */
else
/* keep iterating ... sum over money and the rest of the coins and money - the first item and the full set of coins left*/
loop(money, lcoins.tail,count) + loop(money - lcoins.head,lcoins, count)
}
}
val x = loop(money, coins, 0)
Console println x
x
}
Here's some absolutely straightforward C++ code to solve the problem which did ask for all the combinations to be shown.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
if (argc != 2)
{
printf("usage: change amount-in-cents\n");
return 1;
}
int total = atoi(argv[1]);
printf("quarter\tdime\tnickle\tpenny\tto make %d\n", total);
int combos = 0;
for (int q = 0; q <= total / 25; q++)
{
int total_less_q = total - q * 25;
for (int d = 0; d <= total_less_q / 10; d++)
{
int total_less_q_d = total_less_q - d * 10;
for (int n = 0; n <= total_less_q_d / 5; n++)
{
int p = total_less_q_d - n * 5;
printf("%d\t%d\t%d\t%d\n", q, d, n, p);
combos++;
}
}
}
printf("%d combinations\n", combos);
return 0;
}
But I'm quite intrigued about the sub problem of just calculating the number of combinations. I suspect there's a closed-form equation for it.
The sub problem is a typical Dynamic Programming problem.
/* Q: Given some dollar value in cents (e.g. 200 = 2 dollars, 1000 = 10 dollars),
find the number of combinations of coins that make up the dollar value.
There are only penny, nickel, dime, and quarter.
(quarter = 25 cents, dime = 10 cents, nickel = 5 cents, penny = 1 cent) */
/* A:
Reference: http://andrew.neitsch.ca/publications/m496pres1.nb.pdf
f(n, k): number of ways of making change for n cents, using only the first
k+1 types of coins.
+- 0, n < 0 || k < 0
f(n, k) = |- 1, n == 0
+- f(n, k-1) + f(n-C[k], k), else
*/
#include <iostream>
#include <vector>
using namespace std;
int C[] = {1, 5, 10, 25};
// Recursive: very slow, O(2^n)
int f(int n, int k)
{
if (n < 0 || k < 0)
return 0;
if (n == 0)
return 1;
return f(n, k-1) + f(n-C[k], k);
}
// Non-recursive: fast, but still O(nk)
int f_NonRec(int n, int k)
{
vector<vector<int> > table(n+1, vector<int>(k+1, 1));
for (int i = 0; i <= n; ++i)
{
for (int j = 0; j <= k; ++j)
{
if (i < 0 || j < 0) // Impossible, for illustration purpose
{
table[i][j] = 0;
}
else if (i == 0 || j == 0) // Very Important
{
table[i][j] = 1;
}
else
{
// The recursion. Be careful with the vector boundary
table[i][j] = table[i][j-1] +
(i < C[j] ? 0 : table[i-C[j]][j]);
}
}
}
return table[n][k];
}
int main()
{
cout << f(100, 3) << ", " << f_NonRec(100, 3) << endl;
cout << f(200, 3) << ", " << f_NonRec(200, 3) << endl;
cout << f(1000, 3) << ", " << f_NonRec(1000, 3) << endl;
return 0;
}
The code is using Java to solve this problem and it also works... This method may not be a good idea because of too many loops, but it's really a straight forward way.
public class RepresentCents {
public static int sum(int n) {
int count = 0;
for (int i = 0; i <= n / 25; i++) {
for (int j = 0; j <= n / 10; j++) {
for (int k = 0; k <= n / 5; k++) {
for (int l = 0; l <= n; l++) {
int v = i * 25 + j * 10 + k * 5 + l;
if (v == n) {
count++;
} else if (v > n) {
break;
}
}
}
}
}
return count;
}
public static void main(String[] args) {
System.out.println(sum(100));
}
}
This is a really old question, but I came up with a recursive solution in java that seemed smaller than all the others, so here goes -
public static void printAll(int ind, int[] denom,int N,int[] vals){
if(N==0){
System.out.println(Arrays.toString(vals));
return;
}
if(ind == (denom.length))return;
int currdenom = denom[ind];
for(int i=0;i<=(N/currdenom);i++){
vals[ind] = i;
printAll(ind+1,denom,N-i*currdenom,vals);
}
}
Improvements:
public static void printAllCents(int ind, int[] denom,int N,int[] vals){
if(N==0){
if(ind < denom.length) {
for(int i=ind;i<denom.length;i++)
vals[i] = 0;
}
System.out.println(Arrays.toString(vals));
return;
}
if(ind == (denom.length)) {
vals[ind-1] = 0;
return;
}
int currdenom = denom[ind];
for(int i=0;i<=(N/currdenom);i++){
vals[ind] = i;
printAllCents(ind+1,denom,N-i*currdenom,vals);
}
}
Let C(i,J) the set of combinations of making i cents using the values in the set J.
You can define C as that:
(first(J) takes in a deterministic way an element of a set)
It turns out a pretty recursive function... and reasonably efficient if you use memoization ;)
semi-hack to get around the unique combination problem - force descending order:
$denoms = [1,5,10,25]
def all_combs(sum,last)
return 1 if sum == 0
return $denoms.select{|d| d &le sum && d &le last}.inject(0) {|total,denom|
total+all_combs(sum-denom,denom)}
end
This will run slow since it won't be memoized, but you get the idea.
# short and sweet with O(n) table memory
#include <iostream>
#include <vector>
int count( std::vector<int> s, int n )
{
std::vector<int> table(n+1,0);
table[0] = 1;
for ( auto& k : s )
for(int j=k; j<=n; ++j)
table[j] += table[j-k];
return table[n];
}
int main()
{
std::cout << count({25, 10, 5, 1}, 100) << std::endl;
return 0;
}
This is my answer in Python. It does not use recursion:
def crossprod (list1, list2):
output = 0
for i in range(0,len(list1)):
output += list1[i]*list2[i]
return output
def breakit(target, coins):
coinslimit = [(target / coins[i]) for i in range(0,len(coins))]
count = 0
temp = []
for i in range(0,len(coins)):
temp.append([j for j in range(0,coinslimit[i]+1)])
r=[[]]
for x in temp:
t = []
for y in x:
for i in r:
t.append(i+[y])
r = t
for targets in r:
if crossprod(targets, coins) == target:
print targets
count +=1
return count
if __name__ == "__main__":
coins = [25,10,5,1]
target = 78
print breakit(target, coins)
Example output
...
1 ( 10 cents) 2 ( 5 cents) 58 ( 1 cents)
4 ( 5 cents) 58 ( 1 cents)
1 ( 10 cents) 1 ( 5 cents) 63 ( 1 cents)
3 ( 5 cents) 63 ( 1 cents)
1 ( 10 cents) 68 ( 1 cents)
2 ( 5 cents) 68 ( 1 cents)
1 ( 5 cents) 73 ( 1 cents)
78 ( 1 cents)
Number of solutions = 121
var countChange = function (money,coins) {
function countChangeSub(money,coins,n) {
if(money==0) return 1;
if(money<0 || coins.length ==n) return 0;
return countChangeSub(money-coins[n],coins,n) + countChangeSub(money,coins,n+1);
}
return countChangeSub(money,coins,0);
}
Both: iterate through all denominations from high to low, take one of denomination, subtract from requried total, then recurse on remainder (constraining avilable denominations to be equal or lower to current iteration value.)
If the currency system allows it, a simple greedy algorithm that takes as many of each coin as possible, starting with the highest value currency.
Otherwise, dynamic programming is required to find an optimal solution quickly since this problem is essentially the knapsack problem.
For example, if a currency system has the coins: {13, 8, 1}, the greedy solution would make change for 24 as {13, 8, 1, 1, 1}, but the true optimal solution is {8, 8, 8}
Edit: I thought we were making change optimally, not listing all the ways to make change for a dollar. My recent interview asked how to make change so I jumped ahead before finishing to read the question.
I know this is a very old question. I was searching through the proper answer and couldn't find anything that is simple and satisfactory. Took me some time but was able to jot down something.
function denomination(coins, original_amount){
var original_amount = original_amount;
var original_best = [ ];
for(var i=0;i<coins.length; i++){
var amount = original_amount;
var best = [ ];
var tempBest = [ ]
while(coins[i]<=amount){
amount = amount - coins[i];
best.push(coins[i]);
}
if(amount>0 && coins.length>1){
tempBest = denomination(coins.slice(0,i).concat(coins.slice(i+1,coins.length)), amount);
//best = best.concat(denomination(coins.splice(i,1), amount));
}
if(tempBest.length!=0 || (best.length!=0 && amount==0)){
best = best.concat(tempBest);
if(original_best.length==0 ){
original_best = best
}else if(original_best.length > best.length ){
original_best = best;
}
}
}
return original_best;
}
denomination( [1,10,3,9] , 19 );
This is a javascript solution and uses recursion.
In Scala Programming language i would do it like this:
def countChange(money: Int, coins: List[Int]): Int = {
money match {
case 0 => 1
case x if x < 0 => 0
case x if x >= 1 && coins.isEmpty => 0
case _ => countChange(money, coins.tail) + countChange(money - coins.head, coins)
}
}
This is a simple recursive algorithm that takes a bill, then takes a smaller bill recursively until it reaches the sum, it then takes another bill of same denomination, and recurses again. See sample output below for illustration.
var bills = new int[] { 100, 50, 20, 10, 5, 1 };
void PrintAllWaysToMakeChange(int sumSoFar, int minBill, string changeSoFar)
{
for (int i = minBill; i < bills.Length; i++)
{
var change = changeSoFar;
var sum = sumSoFar;
while (sum > 0)
{
if (!string.IsNullOrEmpty(change)) change += " + ";
change += bills[i];
sum -= bills[i];
if (sum > 0)
{
PrintAllWaysToMakeChange(sum, i + 1, change);
}
}
if (sum == 0)
{
Console.WriteLine(change);
}
}
}
PrintAllWaysToMakeChange(15, 0, "");
Prints the following:
10 + 5
10 + 1 + 1 + 1 + 1 + 1
5 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1
5 + 5 + 1 + 1 + 1 + 1 + 1
5 + 5 + 5
1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1
Duh, I feel stupid right now. Below there is an overly complicated solution, which I'll preserve because it is a solution, after all. A simple solution would be this:
// Generate a pretty string
val coinNames = List(("quarter", "quarters"),
("dime", "dimes"),
("nickel", "nickels"),
("penny", "pennies"))
def coinsString =
Function.tupled((quarters: Int, dimes: Int, nickels:Int, pennies: Int) => (
List(quarters, dimes, nickels, pennies)
zip coinNames // join with names
map (t => (if (t._1 != 1) (t._1, t._2._2) else (t._1, t._2._1))) // correct for number
map (t => t._1 + " " + t._2) // qty name
mkString " "
))
def allCombinations(amount: Int) =
(for{quarters <- 0 to (amount / 25)
dimes <- 0 to ((amount - 25*quarters) / 10)
nickels <- 0 to ((amount - 25*quarters - 10*dimes) / 5)
} yield (quarters, dimes, nickels, amount - 25*quarters - 10*dimes - 5*nickels)
) map coinsString mkString "\n"
Here is the other solution. This solution is based on the observation that each coin is a multiple of the others, so they can be represented in terms of them.
// Just to make things a bit more readable, as these routines will access
// arrays a lot
val coinValues = List(25, 10, 5, 1)
val coinNames = List(("quarter", "quarters"),
("dime", "dimes"),
("nickel", "nickels"),
("penny", "pennies"))
val List(quarter, dime, nickel, penny) = coinValues.indices.toList
// Find the combination that uses the least amount of coins
def leastCoins(amount: Int): Array[Int] =
((List(amount) /: coinValues) {(list, coinValue) =>
val currentAmount = list.head
val numberOfCoins = currentAmount / coinValue
val remainingAmount = currentAmount % coinValue
remainingAmount :: numberOfCoins :: list.tail
}).tail.reverse.toArray
// Helper function. Adjust a certain amount of coins by
// adding or subtracting coins of each type; this could
// be made to receive a list of adjustments, but for so
// few types of coins, it's not worth it.
def adjust(base: Array[Int],
quarters: Int,
dimes: Int,
nickels: Int,
pennies: Int): Array[Int] =
Array(base(quarter) + quarters,
base(dime) + dimes,
base(nickel) + nickels,
base(penny) + pennies)
// We decrease the amount of quarters by one this way
def decreaseQuarter(base: Array[Int]): Array[Int] =
adjust(base, -1, +2, +1, 0)
// Dimes are decreased this way
def decreaseDime(base: Array[Int]): Array[Int] =
adjust(base, 0, -1, +2, 0)
// And here is how we decrease Nickels
def decreaseNickel(base: Array[Int]): Array[Int] =
adjust(base, 0, 0, -1, +5)
// This will help us find the proper decrease function
val decrease = Map(quarter -> decreaseQuarter _,
dime -> decreaseDime _,
nickel -> decreaseNickel _)
// Given a base amount of coins of each type, and the type of coin,
// we'll produce a list of coin amounts for each quantity of that particular
// coin type, up to the "base" amount
def coinSpan(base: Array[Int], whichCoin: Int) =
(List(base) /: (0 until base(whichCoin)).toList) { (list, _) =>
decrease(whichCoin)(list.head) :: list
}
// Generate a pretty string
def coinsString(base: Array[Int]) = (
base
zip coinNames // join with names
map (t => (if (t._1 != 1) (t._1, t._2._2) else (t._1, t._2._1))) // correct for number
map (t => t._1 + " " + t._2)
mkString " "
)
// So, get a base amount, compute a list for all quarters variations of that base,
// then, for each combination, compute all variations of dimes, and then repeat
// for all variations of nickels.
def allCombinations(amount: Int) = {
val base = leastCoins(amount)
val allQuarters = coinSpan(base, quarter)
val allDimes = allQuarters flatMap (base => coinSpan(base, dime))
val allNickels = allDimes flatMap (base => coinSpan(base, nickel))
allNickels map coinsString mkString "\n"
}
So, for 37 coins, for example:
scala> println(allCombinations(37))
0 quarter 0 dimes 0 nickels 37 pennies
0 quarter 0 dimes 1 nickel 32 pennies
0 quarter 0 dimes 2 nickels 27 pennies
0 quarter 0 dimes 3 nickels 22 pennies
0 quarter 0 dimes 4 nickels 17 pennies
0 quarter 0 dimes 5 nickels 12 pennies
0 quarter 0 dimes 6 nickels 7 pennies
0 quarter 0 dimes 7 nickels 2 pennies
0 quarter 1 dime 0 nickels 27 pennies
0 quarter 1 dime 1 nickel 22 pennies
0 quarter 1 dime 2 nickels 17 pennies
0 quarter 1 dime 3 nickels 12 pennies
0 quarter 1 dime 4 nickels 7 pennies
0 quarter 1 dime 5 nickels 2 pennies
0 quarter 2 dimes 0 nickels 17 pennies
0 quarter 2 dimes 1 nickel 12 pennies
0 quarter 2 dimes 2 nickels 7 pennies
0 quarter 2 dimes 3 nickels 2 pennies
0 quarter 3 dimes 0 nickels 7 pennies
0 quarter 3 dimes 1 nickel 2 pennies
1 quarter 0 dimes 0 nickels 12 pennies
1 quarter 0 dimes 1 nickel 7 pennies
1 quarter 0 dimes 2 nickels 2 pennies
1 quarter 1 dime 0 nickels 2 pennies
This blog entry of mine solves this knapsack like problem for the figures from an XKCD comic. A simple change to the items dict and the exactcost value will yield all solutions for your problem too.
If the problem were to find the change that used the least cost, then a naive greedy algorithm that used as much of the highest value coin might well fail for some combinations of coins and target amount. For example if there are coins with values 1, 3, and 4; and the target amount is 6 then the greedy algorithm might suggest three coins of value 4, 1, and 1 when it is easy to see that you could use two coins each of value 3.
Paddy.
public class Coins {
static int ac = 421;
static int bc = 311;
static int cc = 11;
static int target = 4000;
public static void main(String[] args) {
method2();
}
public static void method2(){
//running time n^2
int da = target/ac;
int db = target/bc;
for(int i=0;i<=da;i++){
for(int j=0;j<=db;j++){
int rem = target-(i*ac+j*bc);
if(rem < 0){
break;
}else{
if(rem%cc==0){
System.out.format("\n%d, %d, %d ---- %d + %d + %d = %d \n", i, j, rem/cc, i*ac, j*bc, (rem/cc)*cc, target);
}
}
}
}
}
}
I found this neat piece of code in the book "Python For Data Analysis" by O'reily. It uses lazy implementation and int comparison and i presume it can be modified for other denominations using decimals. Let me know how it works for you!
def make_change(amount, coins=[1, 5, 10, 25], hand=None):
hand = [] if hand is None else hand
if amount == 0:
yield hand
for coin in coins:
# ensures we don't give too much change, and combinations are unique
if coin > amount or (len(hand) > 0 and hand[-1] < coin):
continue
for result in make_change(amount - coin, coins=coins,
hand=hand + [coin]):
yield result
This is the improvement of Zihan's answer. The great deal of unnecessary loops comes when the denomination is just 1 cent.
It's intuitive and non-recursive.
public static int Ways2PayNCents(int n)
{
int numberOfWays=0;
int cent, nickel, dime, quarter;
for (quarter = 0; quarter <= n/25; quarter++)
{
for (dime = 0; dime <= n/10; dime++)
{
for (nickel = 0; nickel <= n/5; nickel++)
{
cent = n - (quarter * 25 + dime * 10 + nickel * 5);
if (cent >= 0)
{
numberOfWays += 1;
Console.WriteLine("{0},{1},{2},{3}", quarter, dime, nickel, cent);
}
}
}
}
return numberOfWays;
}
Straightforward java solution:
public static void main(String[] args)
{
int[] denoms = {4,2,3,1};
int[] vals = new int[denoms.length];
int target = 6;
printCombinations(0, denoms, target, vals);
}
public static void printCombinations(int index, int[] denom,int target, int[] vals)
{
if(target==0)
{
System.out.println(Arrays.toString(vals));
return;
}
if(index == denom.length) return;
int currDenom = denom[index];
for(int i = 0; i*currDenom <= target;i++)
{
vals[index] = i;
printCombinations(index+1, denom, target - i*currDenom, vals);
vals[index] = 0;
}
}
Lots of variations here but couldn't find a PHP solution for the number of combinations anywhere so I'll add one in.
/**
* #param int $money The total value
* #param array $coins The coin denominations
* #param int $sum The countable sum
* #return int
*/
function getTotalCombinations($money, $coins, &$sum = 0){
if ($money == 0){
return $sum++;
} else if (empty($coins) || $money < 0){
return $sum;
} else {
$firstCoin = array_pop(array_reverse($coins));
getTotalCombinations($money - $firstCoin, $coins, $sum) + getTotalCombinations($money, array_diff($coins, [$firstCoin]), $sum);
}
return $sum;
}
$totalCombinations = getTotalCombinations($money, $coins);
/*
* make a list of all distinct sets of coins of from the set of coins to
* sum up to the given target amount.
* Here the input set of coins is assumed yo be {1, 2, 4}, this set MUST
* have the coins sorted in ascending order.
* Outline of the algorithm:
*
* Keep track of what the current coin is, say ccn; current number of coins
* in the partial solution, say k; current sum, say sum, obtained by adding
* ccn; sum sofar, say accsum:
* 1) Use ccn as long as it can be added without exceeding the target
* a) if current sum equals target, add cc to solution coin set, increase
* coin coin in the solution by 1, and print it and return
* b) if current sum exceeds target, ccn can't be in the solution, so
* return
* c) if neither of the above, add current coin to partial solution,
* increase k by 1 (number of coins in partial solution), and recuse
* 2) When current denomination can no longer be used, start using the
* next higher denomination coins, just like in (1)
* 3) When all denominations have been used, we are done
*/
#include <iostream>
#include <cstdlib>
using namespace std;
// int num_calls = 0;
// int num_ways = 0;
void print(const int coins[], int n);
void combine_coins(
const int denoms[], // coins sorted in ascending order
int n, // number of denominations
int target, // target sum
int accsum, // accumulated sum
int coins[], // solution set, MUST equal
// target / lowest denom coin
int k // number of coins in coins[]
)
{
int ccn; // current coin
int sum; // current sum
// ++num_calls;
for (int i = 0; i < n; ++i) {
/*
* skip coins of lesser denomination: This is to be efficient
* and also avoid generating duplicate sequences. What we need
* is combinations and without this check we will generate
* permutations.
*/
if (k > 0 && denoms[i] < coins[k - 1])
continue; // skip coins of lesser denomination
ccn = denoms[i];
if ((sum = accsum + ccn) > target)
return; // no point trying higher denominations now
if (sum == target) {
// found yet another solution
coins[k] = ccn;
print(coins, k + 1);
// ++num_ways;
return;
}
coins[k] = ccn;
combine_coins(denoms, n, target, sum, coins, k + 1);
}
}
void print(const int coins[], int n)
{
int s = 0;
for (int i = 0; i < n; ++i) {
cout << coins[i] << " ";
s += coins[i];
}
cout << "\t = \t" << s << "\n";
}
int main(int argc, const char *argv[])
{
int denoms[] = {1, 2, 4};
int dsize = sizeof(denoms) / sizeof(denoms[0]);
int target;
if (argv[1])
target = atoi(argv[1]);
else
target = 8;
int *coins = new int[target];
combine_coins(denoms, dsize, target, 0, coins, 0);
// cout << "num calls = " << num_calls << ", num ways = " << num_ways << "\n";
return 0;
}
Here's a C# function:
public static void change(int money, List<int> coins, List<int> combination)
{
if(money < 0 || coins.Count == 0) return;
if (money == 0)
{
Console.WriteLine((String.Join("; ", combination)));
return;
}
List<int> copy = new List<int>(coins);
copy.RemoveAt(0);
change(money, copy, combination);
combination = new List<int>(combination) { coins[0] };
change(money - coins[0], coins, new List<int>(combination));
}
Use it like this:
change(100, new List<int>() {5, 10, 25}, new List<int>());
It prints:
25; 25; 25; 25
10; 10; 10; 10; 10; 25; 25
10; 10; 10; 10; 10; 10; 10; 10; 10; 10
5; 10; 10; 25; 25; 25
5; 10; 10; 10; 10; 10; 10; 10; 25
5; 5; 10; 10; 10; 10; 25; 25
5; 5; 10; 10; 10; 10; 10; 10; 10; 10; 10
5; 5; 5; 10; 25; 25; 25
5; 5; 5; 10; 10; 10; 10; 10; 10; 25
5; 5; 5; 5; 10; 10; 10; 25; 25
5; 5; 5; 5; 10; 10; 10; 10; 10; 10; 10; 10
5; 5; 5; 5; 5; 25; 25; 25
5; 5; 5; 5; 5; 10; 10; 10; 10; 10; 25
5; 5; 5; 5; 5; 5; 10; 10; 25; 25
5; 5; 5; 5; 5; 5; 10; 10; 10; 10; 10; 10; 10
5; 5; 5; 5; 5; 5; 5; 10; 10; 10; 10; 25
5; 5; 5; 5; 5; 5; 5; 5; 10; 25; 25
5; 5; 5; 5; 5; 5; 5; 5; 10; 10; 10; 10; 10; 10
5; 5; 5; 5; 5; 5; 5; 5; 5; 10; 10; 10; 25
5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 25; 25
5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 10; 10; 10; 10; 10
5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 10; 10; 25
5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 10; 10; 10; 10
5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 10; 25
5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 10; 10; 10
5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 25
5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 10; 10
5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 10
5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5; 5
Below is a python program to find all combinations of money. This is a dynamic programming solution with order(n) time.
Money is 1,5,10,25
We traverse from row money 1 to row money 25 (4 rows). Row money 1 contains the count if we only consider money 1 in
calculating the number of combinations. Row money 5 produces each column by taking the count in row money r for the
same final money plus the previous 5 count in its own row (current position minus 5). Row money 10 uses row money 5,
which contains counts for both 1,5 and adds in the previous 10 count (current position minus 10). Row money 25 uses row
money 10, which contains counts for row money 1,5,10 plus the previous 25 count.
For example, numbers[1][12] = numbers[0][12] + numbers[1][7] (7 = 12-5) which results in 3 = 1 + 2; numbers[3][12] =
numbers[2][12] + numbers[3][9] (-13 = 12-25) which results in 4 = 0 + 4, since -13 is less than 0.
def cntMoney(num):
mSz = len(money)
numbers = [[0]*(1+num) for _ in range(mSz)]
for mI in range(mSz): numbers[mI][0] = 1
for mI,m in enumerate(money):
for i in range(1,num+1):
numbers[mI][i] = numbers[mI][i-m] if i >= m else 0
if mI != 0: numbers[mI][i] += numbers[mI-1][i]
print('m,numbers',m,numbers[mI])
return numbers[mSz-1][num]
money = [1,5,10,25]
num = 12
print('money,combinations',num,cntMoney(num))
output:
('m,numbers', 1, [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1])
('m,numbers', 5, [1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3])
('m,numbers', 10, [1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 4, 4, 4])
('m,numbers', 25, [1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 4, 4, 4])
('money,combinations', 12, 4)
Java solution
import java.util.Arrays;
import java.util.Scanner;
public class nCents {
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
int cents=input.nextInt();
int num_ways [][] =new int [5][cents+1];
//putting in zeroes to offset
int getCents[]={0 , 0 , 5 , 10 , 25};
Arrays.fill(num_ways[0], 0);
Arrays.fill(num_ways[1], 1);
int current_cent=0;
for(int i=2;i<num_ways.length;i++){
current_cent=getCents[i];
for(int j=1;j<num_ways[0].length;j++){
if(j-current_cent>=0){
if(j-current_cent==0){
num_ways[i][j]=num_ways[i-1][j]+1;
}else{
num_ways[i][j]=num_ways[i][j-current_cent]+num_ways[i-1][j];
}
}else{
num_ways[i][j]=num_ways[i-1][j];
}
}
}
System.out.println(num_ways[num_ways.length-1][num_ways[0].length-1]);
}
}
The below java solution which will print the different combinations as well. Easy to understand. Idea is
for sum 5
The solution is
5 - 5(i) times 1 = 0
if(sum = 0)
print i times 1
5 - 4(i) times 1 = 1
5 - 3 times 1 = 2
2 - 1(j) times 2 = 0
if(sum = 0)
print i times 1 and j times 2
and so on......
If the remaining sum in each loop is lesser than the denomination ie
if remaining sum 1 is lesser than 2, then just break the loop
The complete code below
Please correct me in case of any mistakes
public class CoinCombinbationSimple {
public static void main(String[] args) {
int sum = 100000;
printCombination(sum);
}
static void printCombination(int sum) {
for (int i = sum; i >= 0; i--) {
int sumCopy1 = sum - i * 1;
if (sumCopy1 == 0) {
System.out.println(i + " 1 coins");
}
for (int j = sumCopy1 / 2; j >= 0; j--) {
int sumCopy2 = sumCopy1;
if (sumCopy2 < 2) {
break;
}
sumCopy2 = sumCopy1 - 2 * j;
if (sumCopy2 == 0) {
System.out.println(i + " 1 coins " + j + " 2 coins ");
}
for (int k = sumCopy2 / 5; k >= 0; k--) {
int sumCopy3 = sumCopy2;
if (sumCopy2 < 5) {
break;
}
sumCopy3 = sumCopy2 - 5 * k;
if (sumCopy3 == 0) {
System.out.println(i + " 1 coins " + j + " 2 coins "
+ k + " 5 coins");
}
}
}
}
}
}
Want to improve this post? Provide detailed answers to this question, including citations and an explanation of why your answer is correct. Answers without enough detail may be edited or deleted.
Given a NxN matrix with 0s and 1s. Set every row that contains a 0 to all 0s and set every column that contains a 0 to all 0s.
For example
1 0 1 1 0
0 1 1 1 0
1 1 1 1 1
1 0 1 1 1
1 1 1 1 1
results in
0 0 0 0 0
0 0 0 0 0
0 0 1 1 0
0 0 0 0 0
0 0 1 1 0
A Microsoft Engineer told me that there is a solution that involves no extra memory, just two boolean variables and one pass, so I'm looking for that answer.
BTW, imagine it is a bit matrix, therefore just 1s and 0s are allow to be in the matrix.
Ok, so I'm tired as it's 3AM here, but I have a first try inplace with exactly 2 passes on each number in the matrix, so in O(NxN) and it is linear in the size of the matrix.
I use 1rst column and first row as markers to know where are rows/cols with only 1's. Then, there are 2 variables l and c to remember if 1rst row/column are all 1's also.
So the first pass sets the markers and resets the rest to 0's.
The second pass sets 1 in places where rows and cols where marked to be 1, and resets 1st line/col depending on l and c.
I doubt strongly that I can be done in 1 pass as squares in the beginning depend on squares in the end. Maybe my 2nd pass can be made more efficient...
import pprint
m = [[1, 0, 1, 1, 0],
[0, 1, 1, 1, 0],
[1, 1, 1, 1, 1],
[1, 0, 1, 1, 1],
[1, 1, 1, 1, 1]]
N = len(m)
### pass 1
# 1 rst line/column
c = 1
for i in range(N):
c &= m[i][0]
l = 1
for i in range(1,N):
l &= m[0][i]
# other line/cols
# use line1, col1 to keep only those with 1
for i in range(1,N):
for j in range(1,N):
if m[i][j] == 0:
m[0][j] = 0
m[i][0] = 0
else:
m[i][j] = 0
### pass 2
# if line1 and col1 are ones: it is 1
for i in range(1,N):
for j in range(1,N):
if m[i][0] & m[0][j]:
m[i][j] = 1
# 1rst row and col: reset if 0
if l == 0:
for i in range(N):
m [i][0] = 0
if c == 0:
for j in range(1,N):
m [0][j] = 0
pprint.pprint(m)
This cannot be done in one pass since a single bit has an effect on bits before and after it in any ordering. IOW Whatever order you traverse the array in, you may later come accross a 0 which means you have to go back and change a previous 1 to a 0.
Update
People seem to think that by restricting N to some fixed value (say 8) you can solve this is one pass. Well that's a) missing the point and b) not the original question. I wouldn't post a question on sorting and expect an answer which started "assuming you only want to sort 8 things...".
That said, it's a reasonable approach if you know that N is in fact restricted to 8. My answer above answers the original question which has no such retriction.
So my idea is to use the values in the last row/column as a flag to indicate whether all of the values in the corresponding column/row are 1s.
Using a Zig Zag scan through the entire matrix EXCEPT the final row/column. At each element, you set the value in the final row/column as to the logical AND of itself with the value in the current element. In other words, if you hit a 0, the final row/column will be set to 0. If you it a 1, the value in the final row/column will be 1 only if it was 1 already. In any case set the current element to 0.
When you've finished, your final row/column should have 1s iff the corresponding column/row was filled with 1s.
Do a linear scan through the final row and column and looking for 1s. Set 1s in the corresponding elements in body of the matrix where the final row and column are both 1s.
Coding it will be tricky to avoid off-by-one errors etc but it should work in one pass.
I've got a solution here, it runs in a single pass, and does all processing "in place" with no extra memory (save for growing the stack).
It uses recursion to delay the writing of zeros which of course would destroy the matrix for the other rows and cols:
#include <iostream>
/**
* The idea with my algorithm is to delay the writing of zeros
* till all rows and cols can be processed. I do this using
* recursion:
* 1) Enter Recursive Function:
* 2) Check the row and col of this "corner" for zeros and store the results in bools
* 3) Send recursive function to the next corner
* 4) When the recursive function returns, use the data we stored in step 2
* to zero the the row and col conditionally
*
* The corners I talk about are just how I ensure I hit all the row's a cols,
* I progress through the matrix from (0,0) to (1,1) to (2,2) and on to (n,n).
*
* For simplicities sake, I use ints instead of individual bits. But I never store
* anything but 0 or 1 so it's still fair ;)
*/
// ================================
// Using globals just to keep function
// call syntax as straight forward as possible
int n = 5;
int m[5][5] = {
{ 1, 0, 1, 1, 0 },
{ 0, 1, 1, 1, 0 },
{ 1, 1, 1, 1, 1 },
{ 1, 0, 1, 1, 1 },
{ 1, 1, 1, 1, 1 }
};
// ================================
// Just declaring the function prototypes
void processMatrix();
void processCorner( int cornerIndex );
bool checkRow( int rowIndex );
bool checkCol( int colIndex );
void zeroRow( int rowIndex );
void zeroCol( int colIndex );
void printMatrix();
// This function primes the pump
void processMatrix() {
processCorner( 0 );
}
// Step 1) This is the heart of my recursive algorithm
void processCorner( int cornerIndex ) {
// Step 2) Do the logic processing here and store the results
bool rowZero = checkRow( cornerIndex );
bool colZero = checkCol( cornerIndex );
// Step 3) Now progress through the matrix
int nextCorner = cornerIndex + 1;
if( nextCorner < n )
processCorner( nextCorner );
// Step 4) Finially apply the changes determined earlier
if( colZero )
zeroCol( cornerIndex );
if( rowZero )
zeroRow( cornerIndex );
}
// This function returns whether or not the row contains a zero
bool checkRow( int rowIndex ) {
bool zero = false;
for( int i=0; i<n && !zero; ++i ) {
if( m[ rowIndex ][ i ] == 0 )
zero = true;
}
return zero;
}
// This is just a helper function for zeroing a row
void zeroRow( int rowIndex ) {
for( int i=0; i<n; ++i ) {
m[ rowIndex ][ i ] = 0;
}
}
// This function returns whether or not the col contains a zero
bool checkCol( int colIndex ) {
bool zero = false;
for( int i=0; i<n && !zero; ++i ) {
if( m[ i ][ colIndex ] == 0 )
zero = true;
}
return zero;
}
// This is just a helper function for zeroing a col
void zeroCol( int colIndex ) {
for( int i=0; i<n; ++i ) {
m[ i ][ colIndex ] = 0;
}
}
// Just a helper function for printing our matrix to std::out
void printMatrix() {
std::cout << std::endl;
for( int y=0; y<n; ++y ) {
for( int x=0; x<n; ++x ) {
std::cout << m[y][x] << " ";
}
std::cout << std::endl;
}
std::cout << std::endl;
}
// Execute!
int main() {
printMatrix();
processMatrix();
printMatrix();
}
I don't think it's doable. When you're on the first square and its value is 1, you have no way of knowing what the values of the other squares in the same row and column are. So you have to check those and if there's a zero, return to the first square and change its value to zero. I'll recommend doing it in two passes - the first pass gathers information about which rows and columns must be zeroed out (the information is stored in an array, so we're using some extra memory). The second pass changes the values. I know that's not the solution you're looking for, but I think it's a practical one. The constraints given by you render the problem unsolvable.
I can do it with two integer variables and two passes (up to 32 rows and columns...)
bool matrix[5][5] =
{
{1, 0, 1, 1, 0},
{0, 1, 1, 1, 0},
{1, 1, 1, 1, 1},
{1, 0, 1, 1, 1},
{1, 1, 1, 1, 1}
};
int CompleteRows = ~0;
int CompleteCols = ~0;
// Find the first 0
for (int row = 0; row < 5; ++row)
{
for (int col = 0; col < 5; ++col)
{
CompleteRows &= ~(!matrix[row][col] << row);
CompleteCols &= ~(!matrix[row][col] << col);
}
}
for (int row = 0; row < 5; ++row)
for (int col = 0; col < 5; ++col)
matrix[row][col] = (CompleteRows & (1 << row)) && (CompleteCols & (1 << col));
the problem can be solved in one pass
saving the matrix in an i X j array.
1 0 1 1 0
0 1 1 1 0
1 1 1 1 1
1 0 1 1 1
1 1 1 1 1
one each pass save the values of i and j for an element which is 0 in arrays a and b
when first row is scanned a= 1 b = 2,5
when second row is scanned a=1,2 b= 1,2,5
when third row is scanned no change
when fourth row is scanned a= 1,2,4 and b= 1,2,5
when fifth row is scanned no change .
now print all values as 0 for values of i and j saved in a and b
rest of the values are 1 ie (3,3) (3,4) (5,3) and (5,4)
Another solution that takes two passes, is to accumulate ANDs horizontally and vertically:
1 0 1 1 0 | 0
0 1 1 1 0 | 0
1 1 1 1 1 | 1
1 0 1 1 1 | 0
1 1 1 1 1 | 1
----------+
0 0 1 1 0
I thought I could design such an algorithm using parity bits, Hamming codes or dynamic programming, possibly using those two booleans as a 2-bit number, but I've had no success yet.
Can you please re-check the problem statement with your engineer and let us know? If
there is indeed a solution, I want to keep chipping away at the problem.
Keep a single variable to keep track of what all of the rows ANDed together are.
If a row is -1 (all 1s), then make the next row a reference to that variable
If a row is anything but, it's a 0. You can do everything in one pass. Psuedo-code:
foreach (my $row) rows {
$andproduct = $andproduct & $row;
if($row != -1) {
zero out the row
} else {
replace row with a reference to andproduct
}
}
That should do it, in a single pass -- but there is an assumption here that N is small enough for the CPU to do arithmetic on a single row, else you're going to need to loop over each row to determine if it's all 1s or not, I believe. But given you're asking about algos and not constraining my hardware, I would just start my answer with "Build a CPU that supports N-bit arithmetic..."
Here's one example how it can be done in C. Note I argue that values and arr taken together represent the array, and p and numproduct are my iterator and AND product variables use to implement the problem. (I could have looped over arr with pointer arithmetic to validate my work, but once was enough!)
int main() {
int values[] = { -10, 14, -1, -9, -1 }; /* From the problem spec, converted to decimal for my sanity */
int *arr[5] = { values, values+1, values+2, values+3, values+4 };
int **p;
int numproduct = 127;
for(p = arr; p < arr+5; ++p) {
numproduct = numproduct & **p;
if(**p != -1) {
**p = 0;
} else {
*p = &numproduct;
}
}
/* Print our array, this loop is just for show */
int i;
for(i = 0; i < 5; ++i) {
printf("%x\n",*arr[i]);
}
return 0;
}
This produces 0, 0, 6, 0, 6, which is the result for the given inputs.
Or in PHP, if people think my stack games in C are cheating (I suggest to you that it's not, because I should be able to store the matrix whichever way I please):
<?php
$values = array(-10, 14, -1, -9, -1);
$numproduct = 127;
for($i = 0; $i < 5; ++$i) {
$numproduct = $numproduct & $values[$i];
if($values[$i] != -1) {
$values[$i] = 0;
} else {
$values[$i] = &$numproduct;
}
}
print_r($values);
Am I missing something?
Nice challange. This solution sort of uses just two booleans created on the stack, but the booleans are created several times on the stack since the function is recursive.
typedef unsigned short WORD;
typedef unsigned char BOOL;
#define true 1
#define false 0
BYTE buffer[5][5] = {
1, 0, 1, 1, 0,
0, 1, 1, 1, 0,
1, 1, 1, 1, 1,
1, 0, 1, 1, 1,
1, 1, 1, 1, 1
};
int scan_to_end(BOOL *h,BOOL *w,WORD N,WORD pos_N)
{
WORD i;
for(i=0;i<N;i++)
{
if(!buffer[i][pos_N])
*h=false;
if(!buffer[pos_N][i])
*w=false;
}
return 0;
}
int set_line(BOOL h,BOOL w,WORD N,WORD pos_N)
{
WORD i;
if(!h)
for(i=0;i<N;i++)
buffer[i][pos_N] = false;
if(!w)
for(i=0;i<N;i++)
buffer[pos_N][i] = false;
return 0;
}
int scan(int N,int pos_N)
{
BOOL h = true;
BOOL w = true;
if(pos_N == N)
return 0;
// Do single scan
scan_to_end(&h,&w,N,pos_N);
// Scan all recursive before changeing data
scan(N,pos_N+1);
// Set the result of the scan
set_line(h,w,N,pos_N);
return 0;
}
int main(void)
{
printf("Old matrix\n");
printf( "%d,%d,%d,%d,%d \n", (WORD)buffer[0][0],(WORD)buffer[0][1],(WORD)buffer[0][2],(WORD)buffer[0][3],(WORD)buffer[0][4]);
printf( "%d,%d,%d,%d,%d \n", (WORD)buffer[1][0],(WORD)buffer[1][1],(WORD)buffer[1][2],(WORD)buffer[1][3],(WORD)buffer[1][4]);
printf( "%d,%d,%d,%d,%d \n", (WORD)buffer[2][0],(WORD)buffer[2][1],(WORD)buffer[2][2],(WORD)buffer[2][3],(WORD)buffer[2][4]);
printf( "%d,%d,%d,%d,%d \n", (WORD)buffer[3][0],(WORD)buffer[3][1],(WORD)buffer[3][2],(WORD)buffer[3][3],(WORD)buffer[3][4]);
printf( "%d,%d,%d,%d,%d \n", (WORD)buffer[4][0],(WORD)buffer[4][1],(WORD)buffer[4][2],(WORD)buffer[4][3],(WORD)buffer[4][4]);
scan(5,0);
printf("New matrix\n");
printf( "%d,%d,%d,%d,%d \n", (WORD)buffer[0][0],(WORD)buffer[0][1],(WORD)buffer[0][2],(WORD)buffer[0][3],(WORD)buffer[0][4]);
printf( "%d,%d,%d,%d,%d \n", (WORD)buffer[1][0],(WORD)buffer[1][1],(WORD)buffer[1][2],(WORD)buffer[1][3],(WORD)buffer[1][4]);
printf( "%d,%d,%d,%d,%d \n", (WORD)buffer[2][0],(WORD)buffer[2][1],(WORD)buffer[2][2],(WORD)buffer[2][3],(WORD)buffer[2][4]);
printf( "%d,%d,%d,%d,%d \n", (WORD)buffer[3][0],(WORD)buffer[3][1],(WORD)buffer[3][2],(WORD)buffer[3][3],(WORD)buffer[3][4]);
printf( "%d,%d,%d,%d,%d \n", (WORD)buffer[4][0],(WORD)buffer[4][1],(WORD)buffer[4][2],(WORD)buffer[4][3],(WORD)buffer[4][4]);
system( "pause" );
return 0;
}
This scans in a pattern like:
s,s,s,s,s
s,0,0,0,0
s,0,0,0,0
s,0,0,0,0
s,0,0,0,0
0,s,0,0,0
s,s,s,s,s
0,s,0,0,0
0,s,0,0,0
0,s,0,0,0
and so on
And then changeing the values in this pattern on return on each of the scan functions. (Bottom up):
0,0,0,0,c
0,0,0,0,c
0,0,0,0,c
0,0,0,0,c
c,c,c,c,c
0,0,0,c,0
0,0,0,c,0
0,0,0,c,0
c,c,c,c,c
0,0,0,c,0
and so on
Okay this is a solution that
uses just one extra long value for working storage.
uses no recursion.
one pass of only N, not even N*N.
will work for other values of N but will need new #defines.
#include <stdio.h>
#define BIT30 (1<<24)
#define COLMASK 0x108421L
#define ROWMASK 0x1fL
unsigned long long STARTGRID =
((0x10 | 0x0 | 0x4 | 0x2 | 0x0) << 20) |
((0x00 | 0x8 | 0x4 | 0x2 | 0x0) << 15) |
((0x10 | 0x8 | 0x4 | 0x2 | 0x1) << 10) |
((0x10 | 0x0 | 0x4 | 0x2 | 0x1) << 5) |
((0x10 | 0x8 | 0x4 | 0x2 | 0x1) << 0);
void dumpGrid (char* comment, unsigned long long theGrid) {
char buffer[1000];
buffer[0]='\0';
printf ("\n\n%s\n",comment);
for (int j=1;j<31; j++) {
if (j%5!=1)
printf( "%s%s", ((theGrid & BIT30)==BIT30)? "1" : "0",(((j%5)==0)?"\n" : ",") );
theGrid = theGrid << 1;
}
}
int main (int argc, const char * argv[]) {
unsigned long long rowgrid = STARTGRID;
unsigned long long colGrid = rowgrid;
unsigned long long rowmask = ROWMASK;
unsigned long long colmask = COLMASK;
dumpGrid("Initial Grid", rowgrid);
for (int i=0; i<5; i++) {
if ((rowgrid & rowmask)== rowmask) rowgrid |= rowmask;
else rowgrid &= ~rowmask;
if ((colGrid & colmask) == colmask) colmask |= colmask;
else colGrid &= ~colmask;
rowmask <<= 5;
colmask <<= 1;
}
colGrid &= rowgrid;
dumpGrid("RESULT Grid", colGrid);
return 0;
}
Actually. If you just want to run the algorithm and print out the results (i.e. not restore them, then this can easily be done in one pass. The trouble comes when you try to modify the array as you're running the algorithm.
Here is my solution It just involves ANDing the rows/columns values for a givein (i,j)'s element and printing it out.
#include <iostream>
#include "stdlib.h"
void process();
int dim = 5;
bool m[5][5]{{1,0,1,1,1},{0,1,1,0,1},{1,1,1,1,1},{1,1,1,1,1},{0,0,1,1,1}};
int main() {
process();
return 0;
}
void process() {
for(int j = 0; j < dim; j++) {
for(int i = 0; i < dim; i++) {
std::cout << (
(m[0][j] & m[1][j] & m[2][j] & m[3][j] & m[4][j]) &
(m[i][0] & m[i][1] & m[i][2] & m[i][3] & m[i][4])
);
}
std::cout << std::endl;
}
}
I tried to solve this problem in C#.
I've used two loop variables (i and j) apart from the actual matrix and n representing its dimension
Logic I tried is to:
Calculate AND for rows and cols involved in each concentric square of the matrix
Store it in its corner cells (I've stored them in anti-clockwise order)
Two bool variables are used to retain values of two corners when evaluating a particular square.
This process would end when outer loop (i) is mid way.
Evaluate results of other cells based on the corner cells (for rest of i). Skip the corner cells during this process.
When i reaches n, all cells would have its result except for the corner cells.
Update the corner cells. This is an extra iteration to length of n/2 other than the single pass constraint mentioned in the problem.
Code:
void Evaluate(bool [,] matrix, int n)
{
bool tempvar1, tempvar2;
for (var i = 0; i < n; i++)
{
tempvar1 = matrix[i, i];
tempvar2 = matrix[n - i - 1, n - i - 1];
var j = 0;
for (j = 0; j < n; j++)
{
if ((i < n/2) || (((n % 2) == 1) && (i == n/2) && (j <= i)))
{
// store the row and col & results in corner cells of concentric squares
tempvar1 &= matrix[j, i];
matrix[i, i] &= matrix[i, j];
tempvar2 &= matrix[n - j - 1, n - i - 1];
matrix[n - i - 1, n - i - 1] &= matrix[n - i - 1, n - j - 1];
}
else
{
// skip corner cells of concentric squares
if ((j == i) || (j == n - i - 1)) continue;
// calculate the & values for rest of them
matrix[i, j] = matrix[i, i] & matrix[n - j - 1, j];
matrix[n - i - 1, j] = matrix[n - i - 1, n - i - 1] & matrix[n - j - 1, j];
if ((i == n/2) && ((n % 2) == 1))
{
// if n is odd
matrix[i, n - j - 1] = matrix[i, i] & matrix[j, n - j - 1];
}
}
}
if ((i < n/2) || (((n % 2) == 1) && (i <= n/2)))
{
// transfer the values from temp variables to appropriate corner cells of its corresponding square
matrix[n - i - 1, i] = tempvar1;
matrix[i, n - i - 1] = tempvar2;
}
else if (i == n - 1)
{
// update the values of corner cells of each concentric square
for (j = n/2; j < n; j++)
{
tempvar1 = matrix[j, j];
tempvar2 = matrix[n - j - 1, n - j - 1];
matrix[j, j] &= matrix[n - j - 1, j];
matrix[n - j - 1, j] &= tempvar2;
matrix[n - j - 1, n - j - 1] &= matrix[j, n - j - 1];
matrix[j, n - j - 1] &= tempvar1;
}
}
}
}
One Pass - I have traversed the input only once but used a new array and only two extra Boolean variables.
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
sc.nextLine();
boolean rowDel = false, colDel = false;
int arr[][] = new int[n][n];
int res[][] = new int[n][n];
int i, j;
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
arr[i][j] = sc.nextInt();
res[i][j] = arr[i][j];
}
}
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
if (arr[i][j] == 0)
colDel = rowDel = true; //See if we have to delete the
//current row and column
if (rowDel == true){
res[i] = new int[n];
rowDel = false;
}
if(colDel == true){
for (int k = 0; k < n; k++) {
res[k][j] = 0;
}
colDel = false;
}
}
}
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
System.out.print(res[i][j]);
}
System.out.println();
}
sc.close();
}
While impossible given the constraints, the most space efficient way to do it is by traversing the matrix in an overlaping, alternating row/column fashion, which would make a pattern similar to laying bricks in a zig-zag fashion:
-----
|----
||---
|||--
||||-
Using this, you would go in each row/column, as indicated, and if you encounter a 0 at any time, set a boolean variable, and re-walk that row/column, setting the entries to 0 as you go.
This will require no extra memory, and will only use one boolean variable. Unfortunately, if the "far" edge is set to all be 0, that is the worst case and you walk the whole array twice.
create a result matrix and set all the values to 1.
go through the data matrix as soon as a 0 is encountered, set the result matrix row column to 0
At the end of the first pass, the result matrix will have the correct answer.
Looks pretty simple. Is there a trick I am missing? Are you not allowed to use a result set?
EDIT:
Looks like a F# function, but that is cheating a bit since even though you are doing a single pass, the function can be recursive.
It looks like the interviewer is trying to figure out if you know functional programming.
Well, I came up with a single-pass, in-place (non-recursive) solution using 4 bools and 2 loop counters. I've not managed to reduce it to 2 bools and 2 ints, but I wouldn't be surprised if it was possible. It does around 3 reads and 3 writes of each cell, and it should be O(N^2) ie. linear in the array size.
Took me a couple of hours to puzzle this one out - I wouldn't want to have to come up with it under the pressure of an interview! If I've made a booboo I'm too tired to spot it...
Um... I'm choosing to define "single-pass" as making one sweep through the matrix, rather than touching each value once! :-)
#include <stdio.h>
#include <memory.h>
#define SIZE 5
typedef unsigned char u8;
u8 g_Array[ SIZE ][ SIZE ];
void Dump()
{
for ( int nRow = 0; nRow < SIZE; ++nRow )
{
for ( int nColumn = 0; nColumn < SIZE; ++nColumn )
{
printf( "%d ", g_Array[ nRow ][ nColumn ] );
}
printf( "\n" );
}
}
void Process()
{
u8 fCarriedAlpha = true;
u8 fCarriedBeta = true;
for ( int nStep = 0; nStep < SIZE; ++nStep )
{
u8 fAlpha = (nStep > 0) ? g_Array[ nStep-1 ][ nStep ] : true;
u8 fBeta = (nStep > 0) ? g_Array[ nStep ][ nStep - 1 ] : true;
fAlpha &= g_Array[ nStep ][ nStep ];
fBeta &= g_Array[ nStep ][ nStep ];
g_Array[ nStep-1 ][ nStep ] = fCarriedBeta;
g_Array[ nStep ][ nStep-1 ] = fCarriedAlpha;
for ( int nScan = nStep + 1; nScan < SIZE; ++nScan )
{
fBeta &= g_Array[ nStep ][ nScan ];
if ( nStep > 0 )
{
g_Array[ nStep ][ nScan ] &= g_Array[ nStep-1 ][ nScan ];
g_Array[ nStep-1][ nScan ] = fCarriedBeta;
}
fAlpha &= g_Array[ nScan ][ nStep ];
if ( nStep > 0 )
{
g_Array[ nScan ][ nStep ] &= g_Array[ nScan ][ nStep-1 ];
g_Array[ nScan ][ nStep-1] = fCarriedAlpha;
}
}
g_Array[ nStep ][ nStep ] = fAlpha & fBeta;
for ( int nScan = nStep - 1; nScan >= 0; --nScan )
{
g_Array[ nScan ][ nStep ] &= fAlpha;
g_Array[ nStep ][ nScan ] &= fBeta;
}
fCarriedAlpha = fAlpha;
fCarriedBeta = fBeta;
}
}
int main()
{
memset( g_Array, 1, sizeof(g_Array) );
g_Array[0][1] = 0;
g_Array[0][4] = 0;
g_Array[1][0] = 0;
g_Array[1][4] = 0;
g_Array[3][1] = 0;
printf( "Input:\n" );
Dump();
Process();
printf( "\nOutput:\n" );
Dump();
return 0;
}
i hope you enjoy my 1-pass c# solution
you can retrieve an element with O(1) and only need
the space of one row and one column of the matrix
bool[][] matrix =
{
new[] { true, false, true, true, false }, // 10110
new[] { false, true, true, true, false }, // 01110
new[] { true, true, true, true, true }, // 11111
new[] { true, false, true, true, true }, // 10111
new[] { true, true, true, true, true } // 11111
};
int n = matrix.Length;
bool[] enabledRows = new bool[n];
bool[] enabledColumns = new bool[n];
for (int i = 0; i < n; i++)
{
enabledRows[i] = true;
enabledColumns[i] = true;
}
for (int rowIndex = 0; rowIndex < n; rowIndex++)
{
for (int columnIndex = 0; columnIndex < n; columnIndex++)
{
bool element = matrix[rowIndex][columnIndex];
enabledRows[rowIndex] &= element;
enabledColumns[columnIndex] &= element;
}
}
for (int rowIndex = 0; rowIndex < n; rowIndex++)
{
for (int columnIndex = 0; columnIndex < n; columnIndex++)
{
bool element = enabledRows[rowIndex] & enabledColumns[columnIndex];
Console.Write(Convert.ToInt32(element));
}
Console.WriteLine();
}
/*
00000
00000
00110
00000
00110
*/
1 pass, 2 booleans. I just have to assume the integer indexes in the iterations don't count.
This is not a complete solution but I can't get pass this point.
If I could only determine if a 0 is an original 0 or a 1 that was converted to a 0 then I wouldn't have to use -1's and this would work.
My output is like this:
-1 0 -1 -1 0
0 -1 -1 -1 0
-1 -1 1 1 -1
-1 0 -1 -1 -1
-1 -1 1 1 -1
The originality of my approach is using the first half of the examination of a row or column to determine if it contains a 0 and the last half to set the values - this is done by looking at x and width-x and then y and height-y in each iteration. Based on the results of the first half of the iteration, if a 0 in the row or column was found, I use the last half of the iteration to change the 1's to -1's.
I just realized this could be done with only 1 boolean leaving 1 to ...?
I'm posting this hoping someone might say, "Ah, just do this..." (And I spent way too much time on it not to post.)
Here's the code in VB:
Dim D(,) As Integer = {{1, 0, 1, 1, 1}, {0, 1, 1, 0, 1}, {1, 1, 1, 1, 1}, {1, 1, 1, 1, 1}, {0, 0, 1, 1, 1}}
Dim B1, B2 As Boolean
For y As Integer = 0 To UBound(D)
B1 = True : B2 = True
For x As Integer = 0 To UBound(D)
// Scan row for 0's at x and width - x positions. Halfway through I'll konw if there's a 0 in this row.
//If a 0 is found set my first boolean to false.
If x <= (Math.Ceiling((UBound(D) + 1) / 2) - 1) Then
If D(x, y) = 0 Or D(UBound(D) - x, y) = 0 Then B1 = False
End If
//If the boolean is false then a 0 in this row was found. Spend the last half of this loop
//updating the values. This is where I'm stuck. If I change a 1 to a 0 it will cause the column
//scan to fail. So for now I change to a -1. If there was a way to change to 0 yet later tell if
//the value had changed this would work.
If Not B1 Then
If x >= (Math.Ceiling((UBound(D) + 1) / 2) - 1) Then
If D(x, y) = 1 Then D(x, y) = -1
If D(UBound(D) - x, y) = 1 Then D(UBound(D) - x, y) = -1
End If
End If
//These 2 block do the same as the first 2 blocks but I switch x and y to do the column.
If x <= (Math.Ceiling((UBound(D) + 1) / 2) - 1) Then
If D(y, x) = 0 Or D(y, UBound(D) - x) = 0 Then B2 = False
End If
If Not B2 Then
If x >= (Math.Ceiling((UBound(D) + 1) / 2) - 1) Then
If D(y, x) = 1 Then D(y, x) = -1
If D(y, UBound(D) - x) = 1 Then D(y, UBound(D) - x) = -1
End If
End If
Next
Next
No one is using binary forms? since it's only 1 and 0. We can use binary vectors.
def set1(M, N):
'''Set 1/0s on M according to the rules.
M is a list of N integers. Each integer represents a binary array, e.g.,
000100'''
ruler = 2**N-1
for i,v in enumerate(M):
ruler = ruler & M[i]
M[i] = M[i] if M[i]==2**N-1 else 0 # set i-th row to all-0 if not all-1s
for i,v in enumerate(M):
if M[i]: M[i] = ruler
return M
Here's the test:
M = [ 0b10110,
0b01110,
0b11111,
0b10111,
0b11111 ]
print "Before..."
for i in M: print "{:0=5b}".format(i)
M = set1(M, len(M))
print "After..."
for i in M: print "{:0=5b}".format(i)
And the output:
Before...
10110
01110
11111
10111
11111
After...
00000
00000
00110
00000
00110
You can do something like this to use one pass but an input and output matrix:
output(x,y) = col(xy) & row(xy) == 2^n
where col(xy) is the bits in the column containing the point xy; row(xy) is the bits in the row containing the point xy. n is the size of the matrix.
Then just loop over the input. Possibly expandable to be more space efficient?
One matrix scan, two booleans, no recursion.
How to avoid the second pass?
The second pass is needed to clear the rows or columns when the zero appeares at their end.
However this problem can be solved, because when we scan row #i we already know the row status for the row #i-1. So, while we are scanning the row #i we can simultaneously clear the row #i-1 if it is needed.
The same solution works for columns, but we need to scan rows and columns simultaneously while the data is not changed by the next iteration.
Two booleans are required to store the status of first row and first column, because their values will be changed during the execution of main part of the algorithm.
To avoid adding more booleans we are storing the "clear" flag for the rows and columns in the first row and column of the matrix.
public void Run()
{
const int N = 5;
int[,] m = new int[N, N]
{{ 1, 0, 1, 1, 0 },
{ 1, 1, 1, 1, 0 },
{ 1, 1, 1, 1, 1 },
{ 1, 0, 1, 1, 1 },
{ 1, 1, 1, 1, 1 }};
bool keepFirstRow = (m[0, 0] == 1);
bool keepFirstColumn = keepFirstRow;
for (int i = 1; i < N; i++)
{
keepFirstRow = keepFirstRow && (m[0, i] == 1);
keepFirstColumn = keepFirstColumn && (m[i, 0] == 1);
}
Print(m); // show initial setup
m[0, 0] = 1; // to protect first row from clearing by "second pass"
// "second pass" is performed over i-1 row/column,
// so we use one more index just to complete "second pass" over the
// last row/column
for (int i = 1; i <= N; i++)
{
for (int j = 1; j <= N; j++)
{
// "first pass" - searcing for zeroes in row/column #i
// when i = N || j == N it is additional pass for clearing
// the previous row/column
// j >= i because cells with j < i may be already modified
// by "second pass" part
if (i < N && j < N && j >= i)
{
m[i, 0] &= m[i, j];
m[0, j] &= m[i, j];
m[0, i] &= m[j, i];
m[j, 0] &= m[j, i];
}
// "second pass" - clearing the row/column scanned
// in the previous iteration
if (m[i - 1, 0] == 0 && j < N)
{
m[i - 1, j] = 0;
}
if (m[0, i - 1] == 0 && j < N)
{
m[j, i - 1] = 0;
}
}
Print(m);
}
// Clear first row/column if needed
if (!keepFirstRow || !keepFirstColumn)
{
for (int i = 0; i < N; i++)
{
if (!keepFirstRow)
{
m[0, i] = 0;
}
if (!keepFirstColumn)
{
m[i, 0] = 0;
}
}
}
Print(m);
Console.ReadLine();
}
private static void Print(int[,] m)
{
for (int i = 0; i < m.GetLength(0); i++)
{
for (int j = 0; j < m.GetLength(1); j++)
{
Console.Write(" " + m[i, j]);
}
Console.WriteLine();
}
Console.WriteLine();
}
seems like the following works with no additional space requirements:
first note that multiplying the elements of the row times the elements of the line in which an element is, gives the desired value.
In order not to use any additional space (not making a new matrix and filling it up but instead apply changes to the matrix directly), start top left of the matrix and do the computation for any ixi matrix (that "starts" at (0,0)) before considering any element with any index > i.
hope this works (havent testet)
This is TESTED for different N in C++, and is:
ONE PASS, TWO BOOLS, NO RECURSION, NO EXTRA MEMORY, HOLDS FOR ARBITRARLY LARGE N
(So far none of the solutions here do ALL of these.)
More specifically, I'm amusing two loop counters are okay. I have two const unsigneds, which only exist rather than being computed every time for readability. The outer loop's interval is [0, N], and the inner loop's interval is [1, n - 1]. The switch statement is in the loop mostly exists to show very clearly that it really is just one pass.
Algorithm Strategy:
The first trick is to us a row and a column from the matrix itself to accumulate the content of the matrix, this memory becomes available by offloading all we really need to know from the first row and column into two booleans. The second trick is to get two passes out of one, by using the symmetry of the sub-matrix and its indices.
Algorithm Synopsis:
Scan the first row and store if they are all ones in a boolean, do the same for the first column storing the result in a second boolean.
For the sub-matrix excluding the first row and the first column: iterate through, left to right, top to bottom, as one would read a paragraph. Upon visiting each element, also visit the corresponding element that would be visited if visiting the sub-matrix in reverse. For each element visited AND its value into the where its row crosses the first column, and also AND its value into where its column crosses the first row.
Once the center of the sub-matrix is reached, continue to visit the two elements simultaneously as above. However now set the visited elements' value to the AND of where its row crosses the first column, and of where its column crosses the first row. After this, the sub-matrix is complete.
Use the two boolean variables computed at the begging to set the first row, and the first column to their correct values.
Templatized C++ Implementation:
template<unsigned n>
void SidewaysAndRowColumn(int((&m)[n])[n]) {
bool fcol = m[0][0] ? true : false;
bool frow = m[0][0] ? true : false;
for (unsigned d = 0; d <= n; ++d) {
for (unsigned i = 1; i < n; ++i) {
switch (d) {
case 0:
frow = frow && m[d][i];
fcol = fcol && m[i][d];
break;
default:
{
unsigned const rd = n - d;
unsigned const ri = n - i;
if (d * n + i < rd * n + ri)
{
m[ d][ 0] &= m[ d][ i];
m[ 0][ d] &= m[ i][ d];
m[ 0][ i] &= m[ d][ i];
m[ i][ 0] &= m[ i][ d];
m[rd][ 0] &= m[rd][ri];
m[ 0][rd] &= m[ri][rd];
m[ 0][ri] &= m[rd][ri];
m[ri][ 0] &= m[ri][rd];
}
else
{
m[ d][ i] = m[ d][0] & m[0][ i];
m[rd][ri] = m[rd][0] & m[0][ri];
}
break;
}
case n:
if (!frow)
m[0][i] = 0;
if (!fcol)
m[i][0] = 0;
};
}
}
m[0][0] = (frow && fcol) ? 1 : 0;
}
Ok, I realize that it isn't quite a match, but I got it in one pass using a bool and a byte instead of two bools... close. I also wouldn't vouch for the efficiency of it but these types of questions often require less than optimal solutions.
private static void doIt(byte[,] matrix)
{
byte zeroCols = 0;
bool zeroRow = false;
for (int row = 0; row <= matrix.GetUpperBound(0); row++)
{
zeroRow = false;
for (int col = 0; col <= matrix.GetUpperBound(1); col++)
{
if (matrix[row, col] == 0)
{
zeroRow = true;
zeroCols |= (byte)(Math.Pow(2, col));
// reset this column in previous rows
for (int innerRow = 0; innerRow < row; innerRow++)
{
matrix[innerRow, col] = 0;
}
// reset the previous columns in this row
for (int innerCol = 0; innerCol < col; innerCol++)
{
matrix[row, innerCol] = 0;
}
}
else if ((int)(zeroCols & ((byte)Math.Pow(2, col))) > 0)
{
matrix[row, col] = 0;
}
// Force the row to zero
if (zeroRow) { matrix[row, col] = 0; }
}
}
}
You can sorta do it in one pass -- if you don't count accessing the matrix in random-access order, which eliminates the benefits of doing it single-pass in the first place (cache-coherence/memory-bandwidth).
[edit: simple, but wrong solution deleted]
You should get better performance than any single-pass method by doing it in two passes: one to accumulate row/column info, and one to apply it. The array (in row-major order) is accessed coherently; for arrays exceeding the cache size (but whose rows can fit in cache), data should be read from memory twice, and stored once:
void fixmatrix2(int M[][], int rows, int cols) {
bool clearZeroRow= false;
bool clearZeroCol= false;
for(int j=0; j < cols; ++j) {
if( ! M[0][j] ) {
clearZeroRow= true;
}
}
for(int i=1; i < rows; ++i) { // scan/accumulate pass
if( ! M[i][0] ) {
clearZeroCol= true;
}
for(int j=1; j < cols; ++j) {
if( ! M[i][j] ) {
M[0][j]= 0;
M[i][0]= 0;
}
}
}
for(int i=1; i < rows; ++i) { // update pass
if( M[i][0] ) {
for(int j=0; j < cols; ++j) {
if( ! M[j][0] ) {
M[i][j]= 0;
}
}
} else {
for(int j=0; j < cols; ++j) {
M[i][j]= 0;
}
}
if(clearZeroCol) {
M[i][0]= 0;
}
}
if(clearZeroRow) {
for(int j=0; j < cols; ++j) {
M[0][j]= 0;
}
}
}
The simplest solution I can think of is pasted below. The logic is to record which row and column to set zero while iterating.
import java.util.HashSet;
import java.util.Set;
public class MatrixExamples {
public static void zeroOut(int[][] myArray) {
Set<Integer> rowsToZero = new HashSet<>();
Set<Integer> columnsToZero = new HashSet<>();
for (int i = 0; i < myArray.length; i++) {
for (int j = 0; j < myArray.length; j++) {
if (myArray[i][j] == 0) {
rowsToZero.add(i);
columnsToZero.add(j);
}
}
}
for (int i : rowsToZero) {
for (int j = 0; j < myArray.length; j++) {
myArray[i][j] = 0;
}
}
for (int i : columnsToZero) {
for (int j = 0; j < myArray.length; j++) {
myArray[j][i] = 0;
}
}
for (int i = 0; i < myArray.length; i++) { // record which rows and // columns will be zeroed
for (int j = 0; j < myArray.length; j++) {
System.out.print(myArray[i][j] + ",");
if(j == myArray.length-1)
System.out.println();
}
}
}
public static void main(String[] args) {
int[][] a = { { 1, 0, 1, 1, 0 }, { 0, 1, 1, 1, 0 }, { 1, 1, 1, 1, 1 },
{ 1, 0, 1, 1, 1 }, { 1, 1, 1, 1, 1 } };
zeroOut(a);
}
}
Here is my Ruby implementation with the the test included, This would take O(MN) space. If we want a real time update (like to show the results when we find zeros rather than waiting the first loop of finding zeros) we can just create another class variable like #output and whenever we find a zero we update #output and not #input.
require "spec_helper"
class Matrix
def initialize(input)
#input = input
#zeros = []
end
def solve
#input.each_with_index do |row, i|
row.each_with_index do |element, j|
#zeros << [i,j] if element == 0
end
end
#zeros.each do |x,y|
set_h_zero(x)
set_v_zero(y)
end
#input
end
private
def set_h_zero(row)
#input[row].map!{0}
end
def set_v_zero(col)
#input.size.times do |r|
#input[r][col] = 0
end
end
end
describe "Matrix" do
it "Should set the row and column of Zero to Zeros" do
input = [[1, 3, 4, 9, 0],
[0, 3, 5, 0, 8],
[1, 9, 6, 1, 9],
[8, 3, 2, 0, 3]]
expected = [[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 9, 6, 0, 0],
[0, 0, 0, 0, 0]]
matrix = Matrix.new(input)
expect(matrix.solve).to eq(expected)
end
end
The code below creates a matrix of size m,n. First decide the dimensions of the matrix. I wanted to fill the matrix[m][n] with randomly with numbers between 0..10. Then create another matrix of the same dimensions and fill it with -1s (final matrix). Then iterate through the initial matrix to see if you will hit 0. When you hit on location(x,y), go to the final matrix and fill the row x with 0s and column y with 0s.
At the end read through the final matrix, if the value is -1 (original value) copy the value in the same location of the initial matrix to final.
public static void main(String[] args) {
int m = 5;
int n = 4;
int[][] matrixInitial = initMatrix(m, n); // 5x4 matrix init randomly
int[][] matrixFinal = matrixNull(matrixInitial, m, n);
for (int i = 0; i < m; i++) {
System.out.println(Arrays.toString(matrixFinal[i]));
}
}
public static int[][] matrixNull(int[][] matrixInitial, int m, int n) {
int[][] matrixFinal = initFinal(m, n); // create a matrix with mxn and init it with all -1
for (int i = 0; i < m; i++) { // iterate in initial matrix
for (int j = 0; j < n; j++) {
if(matrixInitial[i][j] == 0){ // if a value is 0 make rows and columns 0
makeZeroX(matrixFinal, i, j, m, n);
}
}
}
for (int i = 0; i < m; i++) { // if value is -1 (original) copy from initial
for (int j = 0; j < n; j++) {
if(matrixFinal[i][j] == -1) {
matrixFinal[i][j] = matrixInitial[i][j];
}
}
}
return matrixFinal;
}
private static void makeZeroX(int[][] matrixFinal, int x, int y, int m, int n) {
for (int j = 0; j < n; j++) { // make all row 0
matrixFinal[x][j] = 0;
}
for(int i = 0; i < m; i++) { // make all column 0
matrixFinal[i][y] = 0;
}
}
private static int[][] initMatrix(int m, int n) {
int[][] matrix = new int[m][n];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
Random rn = new Random();
int random = rn.nextInt(10);
matrix[i][j] = random;
}
}
for (int i = 0; i < m; i++) {
System.out.println(Arrays.toString(matrix[i]));
}
System.out.println("******");
return matrix;
}
private static int[][] initFinal(int m, int n) {
int[][] matrix = new int[m][n];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
matrix[i][j] = -1;
}
}
return matrix;
}
// another approach
/**
* #param matrixInitial
* #param m
* #param n
* #return
*/
private static int[][] matrixNullNew(int[][] matrixInitial, int m, int n) {
List<Integer> zeroRowList = new ArrayList<>(); // Store rows with 0
List<Integer> zeroColumnList = new ArrayList<>(); // Store columns with 0
for (int i = 0; i < m; i++) { // read through the matrix when you hit 0 add the column to zeroColumnList and add
// the row to zeroRowList
for (int j = 0; j < n; j++) {
if (matrixInitial[i][j] == 0) {
if (!zeroRowList.contains(i)) {
zeroRowList.add(i);
}
if (!zeroColumnList.contains(j)) {
zeroColumnList.add(j);
}
}
}
}
for (int a = 0; a < m; a++) {
if (zeroRowList.contains(a)) { // if the row has 0
for (int b = 0; b < n; b++) {
matrixInitial[a][b] = 0; // replace all row with zero
}
}
}
for (int b = 0; b < n; b++) {
if (zeroColumnList.contains(b)) { // if the column has 0
for (int a = 0; a < m; a++) {
matrixInitial[a][b] = 0; // replace all column with zero
}
}
}
return matrixInitial;
}
here is my solution. As you can see from the code, given a M * N matrix, it sets the entire row to zero once it inspects a zero in that row.the time complexity of my solution is O(M * N) .
I am sharing the whole class which has a static populated array for testing and a display array method to see the result in the console.
public class EntireRowSetToZero {
static int arr[][] = new int[3][4];
static {
arr[0][0] = 1;
arr[0][1] = 9;
arr[0][2] = 2;
arr[0][3] = 2;
arr[1][0] = 1;
arr[1][1] = 5;
arr[1][2] = 88;
arr[1][3] = 7;
arr[2][0] = 0;
arr[2][1] = 8;
arr[2][2] = 4;
arr[2][3] = 4;
}
public static void main(String[] args) {
displayArr(EntireRowSetToZero.arr, 3, 4);
setRowToZero(EntireRowSetToZero.arr);
System.out.println("--------------");
displayArr(EntireRowSetToZero.arr, 3, 4);
}
static int[][] setRowToZero(int[][] arr) {
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
if(arr[i][j]==0){
arr[i]=new int[arr[i].length];
}
}
}
return arr;
}
static void displayArr(int[][] arr, int n, int k) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < k; j++) {
System.out.print(arr[i][j] + " ");
}
System.out.println("");
}
}
}