I have a 2d array (a matrix) and I need to find the max sum that can be collected by starting at any position and going down right or down left until I reach an end. I must give an iterative solution.
This is my code
static int maxValue(double[][] field, int posR, int posC) {
int r = field.length;
int c = field[0].length;
int sum = 0;
double[][] temp = new double[r][c];
for (int i = posR; i < r; i++) {
for (int j = posC; j < c; j++) {
if (i == posR && j == posC) {
temp[i][j] = field[posR][posC];
posR++; posC++;
} else if (i == field.length-1) {
temp[i][j] = field[i][j];
break;
} else if (j == field.length-1) {
temp[i][j] = field[i][j];
break;
} else {
temp[i][j] = Math.max(field[i+1][j-1], field[i+1][j+1]);
}
}
}
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
sum += temp[i][j];
}
}
return sum;
}
}
Here is an idea for an iterative solution: You can slide down a row and at the bottom you will find the max. Sounds crazy? Let me explain with code:
public static double maxZicZacSum(double[][] matrix) {
double[] row = matrix[0]; // assign first row
int n = row.length;
for (int i = 1; i < matrix.length; i++) { // for each row, except the first
double[] nextRow = new double[n];
// special cases (left and right edge)
nextRow[0] = row[1] <= 0 ? matrix[i][0] : row[1] + matrix[i][0];
nextRow[n - 1] = row[n - 2] <= 0 ? matrix[i][n - 1] : row[n - 2] + matrix[i][n - 1];
for (int j = 1; j < n - 1; j++) { // for each column except the edges
double d = Math.max(row[j - 1], row[j + 1]); // which cell above is better?
// if d is > 0, then the sum is also better, otherwise use (i,j) as new start
nextRow[j] = d <= 0 ? matrix[i][j] : d + matrix[i][j];
}
row = nextRow; // finally assign nextRow to row for the next iteration
}
// the highest value in row is now the max sum
double max = row[0];
for (int i = 1; i < n; i++)
if (row[i] > max)
max = row[i];
return max;
}
Generally speaking, this is a dynamic programming problem.
The logic is (with row 0 being the top left)
F(row, col) = valueAt(row, col) + max(F(row + 1, col - 1), F(row + 1, col + 1)
Now, you'll notice this is a recursive definition, so no for loops are really needed.
So, in slight pseudocode
int maxValue(double[][] arr, int row, int col) {
if (outOfBounds) return 0;
int value = arr[row][col];
int leftDiag = maxValue(arr, row +1,col - 1);
int rightDiag = maxValue(arr, row + 1, col + 1);
return value + Math.max(leftDiag, rightDiag);
}
Starting at any position, you should be able to call the method and it'll recursively sum values and return the max path.
Related
public static int printStepsToReachBottom(int rows, int columns, String[] array) {
if (rows == 1) {
array[0] = "";
for (int i = 0; i < columns - 1; i++) {
array[0] += "H";
}
return 1;
}
if (columns == 1) {
array[0] = "";
for (int i = 0; i < rows - 1; i++) {
array[0] += "V";
}
return 1;
}
String[] temporary = new String[1000];
int k = 0;
int firstTypeMove = printStepsToReachBottom(rows - 1, columns, array);
for (int i = 0; i < firstTypeMove; i++) {
temporary[k] = array[i] + "V";
k++;
}
int secondTypeMove = printStepsToReachBottom(rows, columns - 1, array);
for (int i = 0; i < secondTypeMove; i++) {
temporary[k] = array[i] + "H";
k++;
}
for (int i = 0; i < secondTypeMove + firstTypeMove; i++) {
array[i] = temporary[i];
}
return secondTypeMove + firstTypeMove;
}
public static void main(String[] args) {
String[] array = new String[1000];
int outputSize = printStepsToReachBottom(2, 2, array);
for (int i = 0; i < outputSize; i++) {
System.out.println(array[i]);
}
}
I can't figure out how this code snippet is working. I didn't understand the logic. It prints All the possible paths to reach the bottom of an m*n matrix
It prints "HV" and "VH" for the 2x2 matrix. Help me.
You can breakdown the code into three parts;
if (rows == 1) {
array[0] = "";
for (int i = 0; i < columns - 1; i++) {
array[0] += "H";
}
return 1;
}
if (columns == 1) {
array[0] = "";
for (int i = 0; i < rows - 1; i++) {
array[0] += "V";
}
return 1;
}
This part is the end case of the recursion. It says that there is no more rows or columns to go and return an array with size 1 either containing H(or H's) or V(or V's)
String[] temporary = new String[1000];
int k = 0;
int firstTypeMove = printStepsToReachBottom(rows - 1, columns, array);
for (int i = 0; i < firstTypeMove; i++) {
temporary[k] = array[i] + "V";
k++;
}
int secondTypeMove = printStepsToReachBottom(rows, columns - 1, array);
for (int i = 0; i < secondTypeMove; i++) {
temporary[k] = array[i] + "H";
k++;
}
The second part executes the recursion through both H and V directions for any given step which adds two more recursive calls to the stack (Although, in execution it performs a depth-first search rather than a breadth-first one, the idea is easier to grasp that way)
int secondTypeMove = printStepsToReachBottom(rows, columns - 1, array);
for (int i = 0; i < secondTypeMove; i++) {
temporary[k] = array[i] + "H";
k++;
}
for (int i = 0; i < secondTypeMove + firstTypeMove; i++) {
array[i] = temporary[i];
}
return secondTypeMove + firstTypeMove;
And the last part collects the outputs from both H and V directions into the global array and returns the number of outputs to the upper stack.
Here is a simpler recursive Depth First Search that will do the same:
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
dfsPrintAllPathesTopToBottom(3,3);
}
//performs dfs to map all possible paths on a rows x columns matrix
//from top left to bottom right by moving right (R) or down (R)
public static void dfsPrintAllPathesTopToBottom(int rows, int columns){
List<String> path = new ArrayList<>();
dfsPrintAllPathesTopToBottom(0, 0,rows,columns,path);
}
public static void dfsPrintAllPathesTopToBottom(int row, int col, int rows, int columns, List<String> path ){
if(row == rows -1 && col == columns -1){//bottom left reached
System.out.println(path);
return;
}
//move right
int newCol = col +1;
if(newCol < columns ){
List<String>newPath = new ArrayList<>(path);
newPath.add("R");//or newPath.add("H")
dfsPrintAllPathesTopToBottom(row, newCol, rows, columns, newPath);
}
//move down
int newRow = row +1;
if(newRow < rows ){
List<String>newPath = new ArrayList<>(path);
newPath.add("D"); //or newPath.add("V")
dfsPrintAllPathesTopToBottom(newRow, col, rows, columns, new ArrayList<>(newPath));
}
}
}
I have an array of size m rows n columns with each cell size is considered as 1x1.
Now I am removing a list of rows and columns from this array, next I want to know the biggest gap that can be formed after removing them.
Example:
Array of size 4 rows and 3 columns, now I am removing rows {1,2,3} and columns {1,2}
This results is an array having biggest gap of 12 cells.
Another Example:
Array of size 4 rows and 4 columns, now I am removing rows {2} and columns {2}
This results is an array having biggest gap of 4 cells.
I have come up with below code that works for this example:
static long process(int n, int m, int[] h, int[] v) {
ArrayList<ArrayList<Long>> array = new ArrayList<ArrayList<Long>>();
for (int r = 0; r <= n; r++) {
ArrayList<Long> temp = new ArrayList<Long>();
for (int c = 0; c <= m; c++) {
temp.add((long) 1);
}
array.add(temp);
}
int[] x = h;
int xnum = x.length;
Arrays.sort(x);
int[] y = v;
int ynum = y.length;
Arrays.sort(y);
// removing bar i means that list at i-1 and at i
for (int a = xnum - 1; a >= 0; a--) {
int i = x[a];
for (int cell = 0; cell < array.get(i).size(); cell++) {
array.get(i).set(cell, array.get(i).get(cell) + array.get(i - 1).get(cell));
}
array.remove(i - 1);
}
ArrayList<ArrayList<Long>> newarray = new ArrayList<ArrayList<Long>>();
for (int col = 0; col < array.get(0).size(); col++) {
ArrayList<Long> temp = new ArrayList<Long>();
for (int row = 0; row < array.size(); row++) {
temp.add(array.get(row).get(col));
}
newarray.add(temp);
}
for (int b = ynum - 1; b >= 0; b--) {
int i = y[b];
for (int cell = 0; cell < newarray.get(i).size(); cell++) {
newarray.get(i).set(cell, newarray.get(i).get(cell) + newarray.get(i - 1).get(cell));
}
newarray.remove(i - 1);
}
long max = 1;
for (ArrayList<Long> arr : newarray) {
for (long num : arr) {
if (num > max)
max = num;
}
}
return max;
}
How can we reduce the time complexity of this code, because the size of rows and columns is:
1 <= rows, columns <= 100000
Let's start by looking at your current solution, by using simple array instead of ArrayList we can reduce this code to:
static long process(int rows, int cols, int[] hor, int[] ver) {
final long[][] a = new long[rows][cols];
for (int i = 0; i < rows; i++) for (int j = 0; j < cols; j++) a[i][j] = 1;
for (int h : hor) for (int j = 0; j < cols; j++) a[h - 1][j] = a[h][j] = a[h - 1][j] + a[h][j];
for (int v : ver) for (int i = 0; i < rows; i++) a[i][v - 1] = a[i][v] = a[i][v - 1] + a[i][v];
long max = 0;
for (int i = 0; i < rows; i++) for (int j = 0; j < cols; j++) max = Math.max(max, a[i][j]);
return max;
}
this code has complexity O(N^2)
but, we should understand that biggest gap will be in place where biggest count of consecutive rows and columns are removed, thus we can simplify algorithm to:
static int maxConsecutive(int[] a) {
Arrays.sort(a);
int max = 0;
int start = 0;
for (int i = 0; i < a.length; i++)
if (a[i] - a[start] == i - start) max = Math.max(max, i - start + 1);
else start = i;
return max;
}
static long process(int rows, int cols, int[] hor, int[] ver) {
long maxH = maxConsecutive(hor);
long maxV = maxConsecutive(ver);
return (maxH + 1) * (maxV + 1);
}
which has complexity O(logN)
I have a project at school where I have to create a Sudoku Program. I have managed to get a Solver algorithm working but not a Generator. I spent a lot of time online to see if people had found ways to make a working one and I found a man named Mark Fredrick Graves, Jr. (https://www.youtube.com/user/mfgravesjr) who provided a very detailed code on the creation of a sudoku grid on his GitHub (https://github.com/mfgravesjr/finished-projects/tree/master/SudokuGridGenerator). However, I felt that using a one dimensional array was unnecessarily difficult in terms of finding the equations to access lines, columns and boxes. I therefore tried to translate his code into a two dimensional array but I am running into issues with some of his sorting methods and what some variables represent like "int step = (a%2==0? rowOrigin + j: colOrigin + j*9);". What I would like to know is how to translate the methods he uses from one dimensional arrays into two dimensional arrays. Below are the methods (code snippets) in question and my half attempt at translating it myself.
public int[] generateGrid(){
ArrayList<Integer> arr = new ArrayList<Integer>(9);
solvedGrid = new int[81];
for(int i = 1; i <= 9; i++) arr.add(i);
//loads all boxes with numbers 1 through 9
for(int i = 0; i < 81; i++){
if(i%9 == 0) {
Collections.shuffle(arr);
}
int perBox = ((i / 3) % 3) * 9 + ((i % 27) / 9) * 3 + (i / 27) * 27 + (i % 3);
solvedGrid[perBox] = arr.get(i%9);
}
//tracks rows and columns that have been sorted
boolean[] sorted = new boolean[81];
for(int i = 0; i < 9; i++){
boolean backtrack = false;
//0 is row, 1 is column
for(int a = 0; a<2; a++){
//every number 1-9 that is encountered is registered
boolean[] registered = new boolean[10]; //index 0 will intentionally be left empty since there are only number 1-9.
int rowOrigin = i * 9;
int colOrigin = i;
ROW_COL: for(int j = 0; j < 9; j++){
//row/column stepping - making sure numbers are only registered once and marking which cells have been sorted
int step = (a%2==0? rowOrigin + j: colOrigin + j*9);
int num = solvedGrid[step];
if(!registered[num]) {
registered[num] = true;
}else {
//if duplicate in row/column
//box and adjacent-cell swap (BAS method)
//checks for either unregistered and unsorted candidates in same box,
//or unregistered and sorted candidates in the adjacent cells
for(int y = j; y >= 0; y--){
int scan = (a%2==0? i * 9 + y: i + 9 * y);
if(solvedGrid[scan] == num){
//box stepping
for(int z = (a%2==0? (i%3 + 1) * 3: 0); z < 9; z++){
if(a%2 == 1 && z%3 <= i%3) {
continue;
}
int boxOrigin = ((scan % 9) / 3) * 3 + (scan / 27) * 27;
int boxStep = boxOrigin + (z / 3) * 9 + (z % 3);
int boxNum = solvedGrid[boxStep];
if((!sorted[scan] && !sorted[boxStep] && !registered[boxNum]) || (sorted[scan] && !registered[boxNum] && (a%2==0? boxStep%9==scan%9: boxStep/9==scan/9))){
solvedGrid[scan] = boxNum;
solvedGrid[boxStep] = num;
registered[boxNum] = true;
continue ROW_COL;
}else if(z == 8) {
//if z == 8, then break statement not reached: no candidates available
//Preferred adjacent swap (PAS)
//Swaps x for y (preference on unregistered numbers), finds occurence of y
//and swaps with z, etc. until an unregistered number has been found
int searchingNo = num;
//noting the location for the blindSwaps to prevent infinite loops.
boolean[] blindSwapIndex = new boolean[81];
//loop of size 18 to prevent infinite loops as well. Max of 18 swaps are possible.
//at the end of this loop, if continue or break statements are not reached, then
//fail-safe is executed called Advance and Backtrack Sort (ABS) which allows the
//algorithm to continue sorting the next row and column before coming back.
//Somehow, this fail-safe ensures success.
for(int q = 0; q < 18; q++){
SWAP: for(int b = 0; b <= j; b++){
int pacing = (a%2==0? rowOrigin+b: colOrigin+b*9);
if(solvedGrid[pacing] == searchingNo){
int adjacentCell = -1;
int adjacentNo = -1;
int decrement = (a%2==0? 9: 1);
for(int c = 1; c < 3 - (i % 3); c++){
adjacentCell = pacing + (a%2==0? (c + 1)*9: c + 1);
//this creates the preference for swapping with unregistered numbers
if((a%2==0 && adjacentCell >= 81)
|| (a%2==1 && adjacentCell % 9 == 0)) {
adjacentCell -= decrement;
}else {
adjacentNo = solvedGrid[adjacentCell];
if(i%3!=0
|| c!=1
|| blindSwapIndex[adjacentCell]
|| registered[adjacentNo]) {
adjacentCell -= decrement;
}
}
adjacentNo = solvedGrid[adjacentCell];
//as long as it hasn't been swapped before, swap it
if(!blindSwapIndex[adjacentCell]){
blindSwapIndex[adjacentCell] = true;
solvedGrid[pacing] = adjacentNo;
solvedGrid[adjacentCell] = searchingNo;
searchingNo = adjacentNo;
if(!registered[adjacentNo]){
registered[adjacentNo] = true;
continue ROW_COL;
}
break SWAP;
}
}
}
}
}
//begin Advance and Backtrack Sort (ABS)
backtrack = true;
break ROW_COL;
}
}
}
}
}
}
if(a%2==0) {
for(int j = 0; j < 9; j++) {
sorted[i*9+j] = true; //setting row as sorted
}
}else if(!backtrack) {
for(int j = 0; j < 9; j++) {
sorted[i+j*9] = true; //setting column as sorted
}
}else {//reseting sorted cells through to the last iteration
//backtrack = false;
for(int j = 0; j < 9; j++) {
sorted[i*9+j] = false;
}
for(int j = 0; j < 9; j++) {
sorted[(i-1)*9+j] = false;
}
for(int j = 0; j < 9; j++) {
sorted[i-1+j*9] = false;
}
for(int j = 0; j < 81; j++) {
sorted[j] = false;
}
i-=2;
}
}
}
if(!isPerfect(solvedGrid)) {
throw new RuntimeException("ERROR: Imperfect grid generated.");
}
return solvedGrid;
}
My code (unfinished)
public int[][] generateGrid(){
ArrayList<Integer> arr = new ArrayList<Integer>(9);
ArrayList<Integer> values = new ArrayList<Integer>(9);
solvedGrid = new int[9][9];
for(int i = 1 ; i <= 9; i++) {
arr.add(i);
values.add(i);
}
//Fill all boxes with number 1 to 9
for(int i = 0; i < 9; i++) {
for(int j = 0; j < 9; j++) {
if(j == 0) {
Collections.shuffle(arr);
}
solvedGrid[(i/3)*3+(j/3)][(i%3)*3+(j%3)] = arr.get(j);
}
}
//boolean[][] sorted = new boolean[9][9];
for(int i = 0; i < 9; i++) {
for(int j = 0; j < 9; j++) {
int[] rowColValues = new int[9];
rowColValues[j] = solvedGrid[0][j];
ArrayList<Integer> occurence = new ArrayList<Integer>();
for(int k = 0; k < rowColValues.length; k++) {
occurence.add((k+1), occurence.get(k+1)+1);
if(occurence.get(k+1) != 1) {
//swap with number in the box that isn't already in rowColValues
//Not sure how to do this...
//Create a method that takes the correct variables as parameters ?
break;
}
}
//Read the sudoku row then column wise and swap values that already exist in the column or row.
}
}
print2DGrid(solvedGrid);
return solvedGrid;
}
I am trying to create a program that returns the maximum square submatrix of 1's from a square matrix of 0's and 1's. Right now I have figured out how to break the square up into a square submatrix starting at each number that equals 1. The problem is, as the program starts to get farther from the starting point of the matrix, it suddenly goes out of bounds, which I am suspecting has to do with how it calculates what part of the matrix to start from for each submatrix.
Here is my code:
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("Enter the number of rows and columns in the matrix (only one input, this is a square matrix): ");
int dimensions = input.nextInt();
int[][] matrix = new int[dimensions][dimensions];
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
int n = input.nextInt();
if (n == 0 || n == 1)
matrix[i][j] = n;
else
System.out.print("Input only 0 or 1");
}
}
int[] largestBlock = findLargestBlock(matrix);
}
public static int[] findLargestBlock(int[][] m) {
int[] solution = new int[3];
//find rows with most consecutive 1's, then find columns with the same # of consecutive 1's
for (int i = 0; i < m.length; i++) {
for (int j = 0; j < m[i].length; j++) {
//"origin" for each iteration is (i, j)
if (m[i][j] == 1)
if (isSquare(m, i, j) == true) {
solution[0] = i; solution[1] = j; solution[2] = getSize(m, i, j);
}
}
}
return solution;
}
public static boolean isSquare(int[][] m, int i, int j) {
int k = m.length - i;
if (m[0].length - j < k)
k = m.length - j;
if (k < 2)
return false;
int[][] testSquare = new int[k][k];
for (int y = i; y < m.length - i; y++) {
for (int x = j; x < m[i].length - j; x++) {
testSquare[y - i][x - j] = m[y][x];
}
}
for (int y = 0; y < testSquare.length; y++) {
for (int x = 1; x < testSquare[y].length; x++) {
if (testSquare[y][x] != testSquare[y][x - 1])
return false;
}
}
for (int x = 0; x < testSquare[0].length; x++) {
for (int y = 1; y < testSquare.length; y++) {
if (testSquare[y][x] != testSquare[y - 1][x])
return false;
}
}
return true;
}
public static int getSize(int[][] m, int i, int j) {
int k = m.length - i;
if (m[0].length - j < k)
k = m.length - j;
return k;
}
I determined that this part of the program was causing the issue, apparently there is some flaw in it that sends the array x- or y- value out of bounds:
public static boolean isSquare(int[][] m, int i, int j) {
int k = m.length - i;
if (m[0].length - j < k)
k = m.length - j;
if (k < 2)
return false;
int[][] testSquare = new int[k][k];
for (int y = i; y < m.length - i; y++) {
for (int x = j; x < m[i].length - j; x++) {
**testSquare[y - i][x - j] = m[y][x];**
}
}
I'm very confused regarding the line in stars/in bold font, as I think this is the line causing the issue. However, I'm not sure how its causing the issue.
I think the loop you are looking for is this - since testSquare is square just start from it make sure its enumerated from 0 to k then find the other matrix indexes - m will never go more than k since k is the minimum so it starts from i and j and goes to i+k and j+k max.
if (m[i].length - j < k)
k = m[i].length - j;
for (int y = 0; y < k; y++) {
for (int x = 0; x < k; x++) {
testSquare[y][x] = m[i+y][j+x];
}
}
I am trying to iterate throughout 2D Array to find a row that its sum equals the sum of two other rows in the same 2D array.
I am having hard time figuring out how to compare before I can reset sum2 and sum3 to zero;
* for sum2: its sum will be just the sum at row (n-1), same as for sum3
* Just need to find a way to compare before resetting sum2 and sum3 to zero
boolean compare(int n, int [][] A)
{
int i, j, k, x, y, p, sum, sum2, sum3, total;
//row
for ( i = 0; i < n; i++)
{
sum = 0;
//col
for ( j = 0; j < n; j++)
sum+= A[i][j];
//row
for ( k = 0; k < n; k++)
{
sum2 = 0;
//col
if (k != i)
for ( x = 0; x < n; x++)
sum2 += A[k][x];
}
for ( y = 0; y < n; y++)
{
sum3 = 0;
if ( (y != k) && (y != i) )
for ( p = 0; p < n; p++)
sum3 += A[y][p];
}
total = sum2 + sum3;
if ( sum == (total) )
return true;
}//for ( i = 0; i < n; i++)
return false;
}
Any input is greatly appreciated
**** Here we go, I updated my code as below:
boolean compare(int n, int [][] A)
{
int i, j, k, x, y;
int [] sumArray = new int[n];
for (i = 0; i < n; i++)
{
sum = 0;
for(j = 0; j < n; j++)
sum += A[i][j];
sumArray[i] = sum;
}
for ( k = 0; k < n; k++)
{
for(x = 0; x < n; x++)
{
if( x != k)
{
for(y = 0; y < n; y++)
{
if( (y != x) && (y != k) )
{
if( sumArray[k] == (sumArray[x] + sumArray[y]) )
return true;
}
}
}
}
}
return false;
}
Seems like it would be easier to calculate the sum of each row and put them in a 1D array. Then you can compare sums of each row in a more concise way and you also avoid computing the sum of each row more than once.
Also, the parameter int n is not needed for the compare() method, since you can just check the length property of the array that gets passed in.
public boolean compare(int[][] arr) {
final int rowLen = arr.length;
int[] sums = new int[rowLen];
// Compute sum of each row
for (int row = 0; row < rowLen; row++) {
int rowSum = 0;
int[] rowArr = arr[row];
for (int col = 0; col < rowArr.length; col++)
rowSum += rowArr[col];
sums[row] = rowSum;
}
// Check if row n equals the sum of any other 2 rows
for (int n = 0; n < sums.length; n++) {
for (int i = 0; i < sums.length; i++) {
for (int j = i + 1; j < sums.length; j++)
if (n != i && n != j && sums[n] == sums[i] + sums[j]) {
// sum of row n equals sums of rows i+j
System.out.println("Sum of row " + n + " is equal to the sums of rows " + i + " and " + j);
return true;
}
}
}
return false;
}
Disclaimer: untested code, but it gets my point accross